'IllegalStateException: Activity has been destroyed' when 'getSupportFragmentManager()' called after Activity restart

后端 未结 5 1316
猫巷女王i
猫巷女王i 2020-12-30 11:57

I have a parent Fragment Activity that has a ViewPager which contains a child ViewPager. The child ViewPager contains Fragments for each page. I communicate between these ch

相关标签:
5条回答
  • 2020-12-30 12:25

    Committing transactions in OnPostResume callback fixed the issue for me. Thanks to following blogpost http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

    @Override
    protected void onPostResume() {
        super.onPostResume();
        // Commit your transactions here.
    }
    
    0 讨论(0)
  • 2020-12-30 12:30

    When you rotate the device, Android saves, destroys, and recreates your Activity and its ViewPager of Fragments. Since the ViewPager uses the FragmentManager of your Activity, it saves and reuses those Fragments for you (and does not create new ones), so they will hold the old references to your (now destroyed) original Activity, and you get that IllegalStateException.

    In your child Fragments, try something like this:

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.v(TAG, "onAttach");
    
        // Check if parent activity implements our callback interface
        if (activity != null) {
            try {
                mParentCallback = (Callbacks) activity;
            }
            catch (ClassCastException e) {
            }
        }
    }
    

    Then when a selection occurs:

    if(mParentCallback != null) {
        mParentCallback.onItemSelected(selectedLink);
    }
    

    Since onAttach gets called as part of the Fragment lifecycle, your Fragments will update their callback reference on rotation.

    0 讨论(0)
  • 2020-12-30 12:31

    I had this problem with nested fragments and none of the stackoverflow solutions worked for me. Just it seems, that there is a bug with support library, when dismissed fragments still store pointers to previous activity (so getFragmentManager() just returns null, because it is called on already destroyed activity), that's why you need to manage pointers yourself. I ended up with a following solution:
    1. In the first level fragment I was saving pointer to the activity in the method

    public void onAttach(Activity activity) {
            super.onAttach(activity);
            parentActivity = activity; // parentActivity is static variable
    }
    

    2. In the activity which handles fragments I ended up with this code:

    private void launchFragment(Fragment fragment, Activity parent) {
                FragmentTransaction transaction;
                if(parent == null)
                    transaction = mFragmentManager.beginTransaction();
                else    // for nested child fragments, workaround for Android parent pointer bug
                    transaction = parent.getFragmentManager().beginTransaction();
                transaction.replace(R.id.container, fragment);
                transaction.addToBackStack(null);
                transaction.commit();
    }
    

    You should pass parentActivity of FIRST level fragment only when you are calling SECOND level (nested) fragments, as it seems that this bug is only with nested ones after you bring your app from foreground.

    0 讨论(0)
  • 2020-12-30 12:33

    Had a similar issue. Basically if the ViewPager just has couple of fragments, then store references to them in current activity. DO NOT call pagerAdapter's getItem() because it creates a new fragment and it is not attached to any activity and that's why we see "Activity has been destroyed" exception. If you don't want to keep fragment references, then you can use findViewWithTag() method to get Fragment object.

    0 讨论(0)
  • 2020-12-30 12:38

    I had a similar issue, I think it is because the fragments are retained and are keeping a reference to a destoryed activity, my solution was to keep a reference to the fragment in the activity e.g Fragment myfragment = null. And then use the following code in MyFragment:

        public void onAttach(Activity activity) {
            super.onAttach(activity);
            ((TestActivity)activity).contentFragment = this;
    }
    
    0 讨论(0)
提交回复
热议问题