0

I use this code in recyclerViewAdapter. I need to open new fragment from fragment.

    @Override
    public void onClick(View view) {

        AppCompatActivity activity = (AppCompatActivity) view.getContext();


        CarDetailFragment carDetailFragment = new CarDetailFragment();
        FragmentManager  fragmentManager = activity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragmentCar, carDetailFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
denvercoder9
  • 2,979
  • 3
  • 28
  • 41
  • YourAppCompatActivityName rather than AppCompatActivity – Nensi Kasundra Apr 17 '20 at 12:25
  • 2
    Does this answer your question? [java.lang.ClassCastException: android.app.Application cannot be cast to androidx.appcompat.app.AppCompatActivity](https://stackoverflow.com/questions/57962537/java-lang-classcastexception-android-app-application-cannot-be-cast-to-androidx) – Amir Dora. Apr 17 '20 at 12:55

4 Answers4

1

Please check the below code and you can direct getContext() in a fragment and cast it to your activity of the current fragment.

Context context= getContext();
CarDetailFragment carDetailFragment = new CarDetailFragment();
FragmentManager  fragmentManager = ((YOUR_ACTIVITY_NAME) context).getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentCar, carDetailFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Nensi Kasundra
  • 1,980
  • 6
  • 21
  • 34
0

Declare a public static context variable in your Fragment and assign getActivity to it and then use this variable in Adapter to your getSupportFragmentManager.

public static Context context; //declare the variable in your Fragment

context=getActivity;// assign it in your Fragment before calling Adapter

Then in Adapter use it like this

FragmentManager fragmentManager= ((AppCompatActivity) YourFragmentName.context).getSupportFragmentManager();

EDIT

As static context variable could cause memory leak so you can use this

    // while calling the adapter pass getActivity as context
    MyAdapter myAdapter = new MyAdapter(getActivity, /* other variables */);

Then in Adapter use it like this

    private Context context;
    public MyAdapter(Context context, /* Other part */ ) {
        this.context = context;
        //other part
      }


   FragmentManager fragmentManager= ((AppCompatActivity) context).getSupportFragmentManager();
MrinmoyMk
  • 551
  • 7
  • 21
  • I have this: public class MainActivity extends AppCompatActivity, but i write public void onClick(View view) inside the recycleView Adapter – Михаил Бит-Савва Apr 17 '20 at 13:09
  • Please look at the edit that I have added if it helps and let me know if it works or not – MrinmoyMk Apr 17 '20 at 13:10
  • @МихаилБит-Савва please check the new edit and let me know how it works – MrinmoyMk Apr 17 '20 at 13:47
  • it works, one more question: app show me new fragment but don`t hide previous? – Михаил Бит-Савва Apr 17 '20 at 16:57
  • @МихаилБит-Савва In that case you try this `FragmentToHide f = new FragmentToHide(); fragmentTransaction.hide(f); fragmentTransaction.add(R.id.fragmentCar, carDetailFragment);`. Actually hide and add is equivalent to replace – MrinmoyMk Apr 17 '20 at 17:24
  • 1
    Don't store activity context in static variables, it's a common cause of memory leaks ([1](https://stackoverflow.com/questions/11908039/android-static-fields-and-memory-leaks), [2](https://blog.mindorks.com/detecting-and-fixing-memory-leaks-in-android), [3](https://medium.com/swlh/context-and-memory-leaks-in-android-82a39ed33002)). – Eugen Pechanec Apr 22 '20 at 08:34
  • @EugenPechanec then we can pass the activity content to the required adapter while calling it. But I think it helped the author as a solution to his question and so there was no good reason for downvoting this answer rather you could just edit the answer – MrinmoyMk Apr 22 '20 at 10:35
  • Why do you think _I_ downvoted your answer? That's not a very nice assumption, I'm just trying to help. That being said, one half of your answer promotes a bad practice (static context), the other half (`AppCompatActivity activity = (AppCompatActivity)view.getContext().getApplicationContext();`) is wrong (you can't cast `Application` to `Activity`). I believe this qualifies a downvote. I already explained my point of view in another answer. – Eugen Pechanec Apr 22 '20 at 10:50
  • @EugenPechanec Yes, I had made that mistake in a hurry but it was of no use, so I had removed it. I had also done a edit to avoid memory leak hope now there is no issue and you may like it – MrinmoyMk Apr 22 '20 at 11:13
  • Context doesn't have fragment manager. Please, focus, there's no hurry. Take the time you need to make good answer. Test your code, improve formatting... – Eugen Pechanec Apr 22 '20 at 11:21
  • Thanks for pointing the mistake. I just forgot to add `(AppCompatActivity) ` – MrinmoyMk Apr 22 '20 at 11:30
  • If you know the context is actually an activity and you cast it to activity, why bother passing `Context`? Why not just pass the activity as `Activity`? – Eugen Pechanec Apr 23 '20 at 14:35
0

Please take the reference from below code ..

public class NewAdapter extends RecyclerView.Adapter<NewAdapter.<Your-View-Holder-Name>> {
    private FragmentActivity activity;

    public ImageAdapter(FragmentActivity mActivity){
        activity = mActivity;

    }

Change your getActivity() to activity as mentioned below..

 @Override
        public void onClick(View view) {
        FragmentManager  fragmentManager = activity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction(); 
        fragmentTransaction.replace(R.id.fragmentCar, carDetailFragment); 
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }

When you make instance of Adapter class in Activity please use following syntax..

 mAdapter = new NewAdapter(MainActivityHomePage.this);
Jaimil Patel
  • 1,301
  • 6
  • 13
0

My guess is your RecyclerView adapter holds a reference to application context and you're using that to create views. The views then hold the context you used to create them, so when you ask them to getContext() they're going to give you the application instead of the activity themed context.

What to keep in mind:

  1. Activity extends Context, so forget about getBaseContext().
  2. When working with views, you want a themed context. If you're inside a View use getContext(). If you're inside an Activity use this. If you're inside Fragment use getContext(). Forget about getApplicationContext() when working with views.
  3. Your adapter doesn't need Context in constructor. The only place you need a context is when creating views and you can get the right Context from the RecyclerView which is going to display the items.

    @Override 
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // parent is the RecyclerView.
        Context context = parent.getContext();
        // TODO Inflate your view and return view holder.
    }
    

Even if you follow all this you don't get a guarantee that View.getContext() will get you an Activity. It could be a ContextThemeWrapper.

Start thinking about the app architecture. The adapter probably shouldn't know anything about activities or fragments or fragment transactions. The adapter should take data and turn them into views. In the other direction it should take clicks from user and notify some listener. The adapter should take a onClickListener constructor parameter, which you prepared inside the activity (which knows how to do fragment transactions).

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124