android java How to override toString of ParseUser in nested class - java

In Android, I am trying to override the toString() of the ParseUser for use in my listview, using
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseQuery;
import com.parse.ParseUser;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
*/
public class ExampleFragment extends Fragment {
public ExampleFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_example, container, false);
final ListView listView = (ListView) rootView.findViewById(R.id.exampleListView);
ParseQuery query = User.getQuery();
query.findInBackground(new FindCallback<User>() {
public void done(List<User> objects, ParseException e) {
if (e == null) {
// The query was successful.
listView.setAdapter(new ArrayAdapter<User>(rootView.getContext(), android.R.layout.simple_list_item_1, objects));
for (User user : objects) {
Log.i("AppInfo", "Added " + user.toString());
}
} else {
// Something went wrong.
}
}
});
return rootView;
}
public class User extends ParseUser {
#Override
public String toString() {
Log.i("AppInfo", "Username: " + getUsername());
return getUsername();
}
}
}
Seems simple enough. I had this nested in my fragment class and it crashed with this
java.lang.ClassCastException: com.parse.ParseUser cannot be cast to com.mycompany.myproject.ExampleFragment$User
but when I move it into its own subclass (where it gets its own entry in the explorer view in android studio), it works perfectly.
Is there a reason it does not work nested in my fragment class? Seems a bit unnecessary to create its own subclass just to override one function.
UPDATE: If I remove the for loop part it does not error out, but it still does not call my overridden toString() as the listview returns com.parse.ParseUser#etcetcetc.

make sure you have do these 2 things
1.register class before Parse.initialize
ParseObject.registerSubclass(User.class);
2.use annotation to specified the class mapping to waht Class
#ParseClassName("_User")
public class User extends ParseUser {
...
}
here is the reference.
https://parse.com/docs/android/guide#objects-subclassing-parseobject

Related

Why can't the Java compiler find my Hilt class in launchFragmentInHiltContainer?

I'm trying to implement the custom launchFragmentInHiltContainer() method in a Java project, and I've already gone through all the hoops of setting up kotlin and refactoring the reified parameters. However, when I try to compile the project, I am greeted by this puzzling error:
C:\Users\jedwa\AndroidStudioProjects\AppName\app\src\androidTest\java\com\example\appname\MainActivityTest.java:55: error: cannot access Hilt_FragmentPersonalDetails
HiltExtKt.launchFragmentInHiltContainer(FragmentPersonalDetails.class);
^
class file for com.example.appname.fragments.Hilt_FragmentPersonalDetails not found
FragmentPersonalDetails is a hilt-enabled fragment and works fine in production code. What is strange is that replacing FragmentPersonalDetails.class with a NonHiltFragment.class will allow the project to compile just fine.
What it will not do, however is stop a runtime error from occurring, which may be related. On replacing FragmentPersonalDetails with NonHiltFragment, I get:
java.lang.RuntimeException: Hilt test, MainActivityTest, is missing generated file: com.example.appname.MainActivityTest_TestComponentDataSupplier. Check that the test class is annotated with #HiltAndroidTest and that the processor is running over your test.
which I have seen before, except this time I most definitely do have #HiltAndroidTest on my test class. I've finally hit the point where the error is internal enough that I have no idea how to go about fixing it, though it seems like a dependency error of some sort. Files provided below for reference.
The hilt-enabled FragmentPersonalDetails
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import com.example.atease.R;
import com.example.atease.databinding.FragmentPersonalDetailsBinding;
import com.example.atease.viewmodels.LoginViewModel;
import dagger.hilt.android.AndroidEntryPoint;
#AndroidEntryPoint
public class FragmentPersonalDetails extends Fragment {
private FragmentPersonalDetailsBinding binding;
#Override
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentPersonalDetailsBinding.inflate(inflater, container, false);
binding.setLifecycleOwner(this);
NavController navController = NavHostFragment.findNavController(this);
ViewModelStoreOwner store = navController.getViewModelStoreOwner(R.id.login_graph);
binding.setViewModel(new ViewModelProvider(store).get(LoginViewModel.class));
return binding.getRoot();
}
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.nextButton.setOnClickListener(view1 ->
NavHostFragment.findNavController(FragmentPersonalDetails.this)
.navigate(R.id.action_FragmentPersonalDetails_to_FragmentEmploymentDetails));
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
The test class that won't compile
import androidx.test.espresso.IdlingRegistry;
import androidx.test.espresso.accessibility.AccessibilityChecks;
import com.example.atease.fragments.SecondFragment;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import javax.inject.Inject;
import dagger.hilt.android.testing.HiltAndroidRule;
import dagger.hilt.android.testing.HiltAndroidTest;
/**
* Instrumented test, which will execute on an Android device.
*
* #see Testing documentation
*/
#HiltAndroidTest
public class MainActivityTest {
#Inject DataBindingIdlingResource bindingIdlingResource;
#BeforeClass
public static void enableAccessibility() {
AccessibilityChecks.enable().setRunChecksFromRootView(true);
}
#Before
public void init() {
hiltRule.inject();
IdlingRegistry.getInstance().register(bindingIdlingResource);
}
#After
public void tearDown() {
IdlingRegistry.getInstance().unregister(bindingIdlingResource);
}
#Rule
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
//cycles through the nav-bar
#Test
public void testNavbar() {
HiltExtKt.launchFragmentInHiltContainer(SecondFragment.class);
}
}
My implementation of launchFragmentinHiltContainer. The only difference is that I took out the reified parameter types and added the extra class parameter, in order to be able to reference the methods from Java.
import android.content.ComponentName
import android.content.Intent
import android.os.Bundle
import androidx.annotation.StyleRes
import androidx.core.util.Preconditions
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import kotlinx.coroutines.ExperimentalCoroutinesApi
#JvmOverloads
#ExperimentalCoroutinesApi
inline fun <T : Fragment> launchFragmentInHiltContainer(
fragmentType: Class<T>,
fragmentArgs: Bundle? = null,
#StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
crossinline action: Fragment.() -> Unit = {}
) {
val startActivityIntent = Intent.makeMainActivity(
ComponentName(
ApplicationProvider.getApplicationContext(),
HiltTestActivity::class.java
)
).putExtra("androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY",
themeResId)
ActivityScenario.launch<HiltTestActivity>(startActivityIntent).onActivity { activity ->
val fragment: Fragment = activity.supportFragmentManager.fragmentFactory.instantiate(
Preconditions.checkNotNull(fragmentType.classLoader),
fragmentType.name
)
fragment.arguments = fragmentArgs
activity.supportFragmentManager
.beginTransaction()
.add(android.R.id.content, fragment, "")
.commitNow()
fragment.action()
}
}
#JvmOverloads
#ExperimentalCoroutinesApi
inline fun <T : Fragment> launchFragmentInHiltContainer(
fragmentType: Class<T>,
fragmentArgs: Bundle? = null,
#StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
factory: FragmentFactory,
crossinline action: Fragment.() -> Unit = {}
) {
val startActivityIntent = Intent.makeMainActivity(
ComponentName(
ApplicationProvider.getApplicationContext(),
HiltTestActivity::class.java
)
).putExtra("androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY",
themeResId)
ActivityScenario.launch<HiltTestActivity>(startActivityIntent).onActivity { activity ->
activity.supportFragmentManager.fragmentFactory = factory
val fragment: Fragment = activity.supportFragmentManager.fragmentFactory.instantiate(
Preconditions.checkNotNull(fragmentType.classLoader),
fragmentType.name
)
fragment.arguments = fragmentArgs
activity.supportFragmentManager
.beginTransaction()
.add(android.R.id.content, fragment, "")
.commit()
fragment.action()
}
}
Just rewrite the function in Java. I changed the signature to match the original FragmentScenario.launchInContainer.
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import java.util.Objects;
public class HiltHelper {
public static void launchFragmentInHiltContainer(Class<? extends Fragment> fragmentClass, Bundle fragmentArgs, #StyleRes int themeResId) {
Intent intent = Intent.makeMainActivity(new ComponentName(ApplicationProvider.getApplicationContext(), HiltTestActivity.class))
.putExtra("androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY", themeResId);
ActivityScenario.launch(intent)
.onActivity(activity -> {
Fragment fragment = ((AppCompatActivity) activity).getSupportFragmentManager().getFragmentFactory()
.instantiate(Objects.requireNonNull(fragmentClass.getClassLoader()), fragmentClass.getName());
fragment.setArguments(fragmentArgs);
((AppCompatActivity) activity).getSupportFragmentManager()
.beginTransaction()
.add(android.R.id.content, fragment, "")
.commitNow();
});
}
}

Required: com.app.appname.mainactivity, Found: androidx.fragment.app.FragmentActivity

I just started to work in android studio. Tutorials are helping and all, but I can't find any help for this problem (it might be obvious, but I don't see it).
My problem comes after implementing the communication between the fragment activity and main activity.
Error after compiling is:
error: incompatible types: FragmentActivity cannot be converted to MainActivity
After going to where the error is, it says:
Incompatible types.
Required: com.app.appname.mainactivity
Found: androidx.fragment.app.FragmentActivity
This is the code for my fragment, where the error happens:
(names are in my language)
package com.ors.herobomb;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class Uspeh extends Fragment {
EditText upis;
Button poslji;
public Uspeh() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View p = inflater.inflate(R.layout.fragment_uspeh, container, false);
upis = p.findViewById(R.id.hero);
poslji = p.findViewById(R.id.poslji);
poslji.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String ode = upis.getText().toString();
if(ode.length()>1){
MainActivity main = getActivity();
main.send(ode);
}
}
});
return p;
}
}
Answer provided by Daniel.
Replacing:
MainActivity main = getActivity();
With:
MainActivity main = (MainActivity) getActivity();
Solved my problem.

Constructor within activity is undefined

I have been fighting with this error for a couple of hours and I am not able to continue. I need your help here!
I am trying to replace my previous TabNavigation at ActionBar by a ViewPager in SDK21, looking at comments within StackOverflow I found this webpage, where the use of PagerTabStrip is described with an example, so I tried to implement it in my activity, however I am getting an strange error.
I tried to google the problem and all the suggestions are not really applicable to my problem (wrong parameters in the constructor are the usual errors) . I also reproduced the error with a simple Activity in order to avoid anything I have in my previous activity, but the error keeps. I attach you here the code I replicated isolated:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TestActivity extends Activity {
CustomPagerAdapter mCustomPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adding_users_to_list);
mCustomPagerAdapter = new CustomPagerAdapter(getFragmentManager(), this.getApplicationContext());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCustomPagerAdapter);
}
class CustomPagerAdapter extends FragmentPagerAdapter {
Context mContext;
public CustomPagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
// Create fragment object
Fragment fragment = new DemoFragment();
// Attach some data to the fragment
// that we'll use to populate our fragment layouts
Bundle args = new Bundle();
args.putInt("page_position", position + 1);
// Set the arguments on the fragment
// that will be fetched in the
// DemoFragment#onCreateView
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + (position + 1);
}
}
class DemoFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout resource that'll be returned
View rootView = inflater.inflate(R.layout.fragment_users, container, false);
// Get the arguments that was supplied when
// the fragment was instantiated in the
// CustomPagerAdapter
Bundle args = getArguments();
((TextView) rootView.findViewById(R.id.text_option)).setText("Page " + args.getInt("page_position"));
return rootView;
}
}
}
I am getting in the call to the constructor the following error:
"The constructor TestActivity.CustomePageAdapter(FragmentManager, Context) is undefined"
In here:
mCustomPagerAdapter = new CustomPagerAdapter(getFragmentManager(), this.getApplicationContext());
I have tried to introduce the Adapter outside and inside the activity definition and is still not working. Is likely to be something simple, but... I can't see it and I need other eyes. Any idea what I am doing wrong?
change the import of the activity to:
import android.support.v4.app.FragmentActivity;
Also change constructor to:
mCustomPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager(), this.getApplicationContext());
The reason is that your activity is used from the ADT:
import android.app.Activity;
and the Fragments used from the support package:
import android.support.v4.app.FragmentManager;
change the import of the activity to:
import android.support.v4.app.FragmentActivity;

Cannot make a static reference to the non-static method show(FragmentManager, String) from the type DialogFragment

Hey Guys i'm having a few issues with I think importation. I'm getting the error message in the title under MyDialog.show(manager, "MyDialog");
Anybody know what it means? I'm thinking some issue with importing but i'm not to sure.
Rest of code:
package com.example.sub_assignment1_2;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
/**
* A simple {#link Fragment} subclass.
*
*/
public class FragmentB extends Fragment implements MyDialog.Communicator {
public FragmentB() {
// Required empty public constructor
}
public void showDialog(View v)
{
FragmentManager manager=getFragmentManager();
MyDialog myDialog=new MyDialog();
MyDialog.show(manager, "MyDialog");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_b, container, false);
}
#Override
public void onDialogMessage(String message) {
Toast.makeText(this, message,Toast.LENGTH_SHORT).show();
}
}
I'm also having an issue under Toast.makeText(this, message,Toast.LENGTH_SHORT).show(); The displayed error is: Toast.makeText(this, message,Toast.LENGTH_SHORT).show(); Which i'm also thinking is an import error?
If anybody could help that would be great.
In MyDialog.show(manager, "MyDialog");
should you not have myDialog.show - ie the instance not the class? Calling the method on the class name would be a static reference, which doesn't require an instance.

Getting the position of a list item in Android

So I have this class here:
package phil.droid.game;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
public class GameList extends GamesTrialActivity
{
private ListView lv1;
protected String Game_names[]={"God of War","FOS RO DAH", "dhwaud"};
private String Game_pics[]={"God of War","God of War II"};
private int pos;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.gamelist);
lv1=(ListView)findViewById(R.id.thegamelist);
lv1.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , Game_names));
lv1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
pos = position;
Intent i = new Intent(GameList.this, game_viewer.class);
startActivity(i);
}
});
}
}
And then this VclassV extends the one ^above^
package phil.droid.game;
import android.os.Bundle;
import android.widget.TextView;
public class game_viewer extends GameList
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game_template);
TextView game_title = (TextView)findViewById(R.id.GameTitle);
game_title.setText("" + pos);
}
}
The problem is at the moment that the last bit recognizes "pos" as "0" no matter what option I click on. Can someone suggest a way to make it so pos is recognized as the number element that's clicked on in the previous class?
Make pos protected, not private.
What you're trying to do can't work: The newly launched activity will not share the same storage as the parent, even if they inherit. The only way it would be possible is if the value was static, but that's not a good idea either.
What you should do instead is to send the data as part of the intent before starting the activity, e.g.:
intent.putExtra("pos", position);
and then you can pull it out in the new activity with
getIntent().getIntExtra("pos", -1); // -1 is used as default value
Also, game_viewer should most likely be a separate activity, rather than inherit from GameList.

Categories