Getting the error “Java.lang.IllegalStateException Activity has been destroyed” when using tabs with ViewPager

心已入冬 提交于 2019-11-29 00:22:30

This seems to be a bug in the newly added support for nested fragments. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity. A short-term workaround that fixed it for me is to add the following to onDetach() of every Fragment which you call getChildFragmentManager() on:

@Override
public void onDetach() {
    super.onDetach();

    try {
        Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
        childFragmentManager.setAccessible(true);
        childFragmentManager.set(this, null);

    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

I'm having exactly the same problem. The only workaround I've found, is to replace the fragments by a new instance, each time the tabs are changed.

ft.replace(R.id.fragment_container, Fragment.instantiate(PlayerMainActivity.this, fragment.getClass().getName()));

Not a real solution, but i haven't found a way to reuse the previous fragment instance...

user1050133

I encountered the same issue when calling super.onCreate() at the end of my method. The reason: attachActivity() is called in onCreate() of FragmentActivity. When overriding onCreate() and, for example, creating tabs, the Tab manager will try to switch to a fragment while not having the activity attached to the FragmentManager.

Simple solution: Move the call to super.onCreate() to the head of the function body.

In general, it seems there are loads of reasons this issue may occur. This is just another one ...

Matthias

sgarman

Wanted to add that my problem was in an activity where I tried to make a FragmentTransaction in onCreate BEFORE I called super.onCreate(). I just moved super.onCreate() to top of function and was worked fine.

I had this error because I was using LocalBroadcastManager and I did:

unregisterReceiver(intentReloadFragmentReceiver);

instead of:

LocalBroadcastManager.getInstance(this).unregisterReceiver(intentReloadFragmentReceiver);

I encountered the same issue and lateron found out that, I have missed call to super.onCreate( savedInstanceState ); in onCreate() of FragmentActivity.

I got the very same error when trying to access the child FragmentManager before the fragment was fully initialized (i.e. attached to the Activity or at least onCreateView() called). Else the FragmentManager gets initialized with a null Activity causing the aforementioned exception.

I force the fragment containing the child fragment to NULL in onPause and it fixes my problem

fragment = null;

I know this is an old post, but the suggested answers didn't work on my end. I want to leave this here just in case someone will find it useful.

What i did is:

@Override
public void onResume() {
    super.onResume();
    // add all fragments
    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    for(Fragment fragment : fragmentPages){
        String tag = fragment.getClass().getSimpleName();
        fragmentTransaction.add(R.id.contentPanel, fragment, tag);
        if(fragmentPages.indexOf(fragment) != currentPosition){
            fragmentTransaction.hide(fragment);
        } else {
            lastTag = tag;
        }
    }
    fragmentTransaction.commit();
}

Then in:

@Override
public void onPause() {
    super.onPause();
    // remove all attached fragments
    for(Fragment fragment: fragmentPages){
        getChildFragmentManager().beginTransaction().remove(fragment).commit();
    }
}

I had this problem and I couldn't find the solution here, so I want to share my solution in case someone else has this problem again.

I had this code:

public void finishAction() {
  onDestroy();
  finish();
}

and solved the problem by deleting the line "onDestroy();"

public void finishAction() {
  finish();
}

The reason I wrote the initial code: I know that when you execute "finish()" the activity calls "onDestroy()", but I'm using threads and I wanted to ensure that all the threads are destroyed before starting the next activity, and it looks like "finish()" is not always immediate. I need to process/reduce a lot of “Bitmap” and display big “bitmaps” and I’m working on improving the use of the memory in my app

Now I will kill the threads using a different method and I’ll execute this method from "onDestroy();" and when I think I need to kill all the threads.

public void finishAction() {
  onDestroyThreads();
  finish();
}

I had this issue and realized it was because I was calling setContentView(int id) twice in my Activity's onCreate

This one drove me crazy for Xamarin.

I ran into this with a ViewPager implementation for TabLayout WITHIN a Fragment, that is itself implemented in the DrawerLayout:

 - DrawerLayout
   - DrawerFragment
     - TabLayout
     - TabViewPager
       - TabViewPagerFragments

So you have to implement the following code in your DrawerFragment. Be aware to choose the correct FragmentManager-Path. Because you might have two different FragmentManager References:

  1. Android.Support.V4.App.FragmentManager
  2. Android.App.FragmentManager

--> Choose the one you use. If you want to make use of the ChildFragmentManager, you had to use the class declaration Android.App.FragmentManager for your ViewPager!

Android.Support.V4.App.FragmentManager

Implement the following Method in your "Main" Fragment - in this example: DrawerFragment

public override void OnDetach() {
    base.OnDetach();
    try {
        Fragment x = this;
        var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static);
        IntPtr classRef = (IntPtr)classRefProp.GetValue(x);
        var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/support/v4/app/FragmentManagerImpl;");
        JNIEnv.SetField(base.Handle, field, IntPtr.Zero);
    }
    catch (Exception e) {
        Log.Debug("Error", e+"");
    }
}

Android.App.FragmentManager

public class TabViewPager: Android.Support.V13.App.FragmentPagerAdapter {}

That means you had to init the ViewPager with Android.App.FragmentManager.

Implement the following Method in your "Main" Fragment - in this example: DrawerFragment

public override void OnDetach() {
    base.OnDetach();
    try {
        Fragment x = this;
        var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static);
        IntPtr classRef = (IntPtr)classRefProp.GetValue(x);
        var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/app/FragmentManagerImpl;");
        JNIEnv.SetField(base.Handle, field, IntPtr.Zero);
    }
    catch (Exception e) {
        Log.Debug("Error", e+"");
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!