causing a java.IllegalStateException error, No Activity, only when navigating to Fragment for the SECOND time

15,993

Solution 1

I followed the link in jeremyvillalobos answer (which was very helpful) that led me to this workaround.

public class CustomFragment extends Fragment {
    private static final Field sChildFragmentManagerField;

    static {
        Field f = null;
        try {
            f = Fragment.class.getDeclaredField("mChildFragmentManager");
            f.setAccessible(true);
        } catch (NoSuchFieldException e) {
            Log.e(LOGTAG, "Error getting mChildFragmentManager field", e);
        }
        sChildFragmentManagerField = f;
    }

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

        if (sChildFragmentManagerField != null) {
            try {
                sChildFragmentManagerField.set(this, null);
            } catch (Exception e) {
                Log.e(LOGTAG, "Error setting mChildFragmentManager field", e);
            }
        }
    }

    ...
}

It works for me well, without the need to reinstantiate the fragment.

Solution 2

This appears to be a bug reported at

https://code.google.com/p/android/issues/detail?id=42601

The variable

FragmentManagerImpl mChildFragmentManager;

In Fragment.java is not set to null on detach. So the next time the fragment is loaded, the variable still points to the last parent.

As discussed on that thread, a workaround is to reinstantiate the Fragment.

In my case, I was switching between fragments in an ActionBar tab. The troubled Fragment has nested Fragments and was crashing the app when coming back to the file loader Fragment. So this is the work-around code:

class MainTabsListener implements ActionBar.TabListener {
    public Fragment fragment;
    public int TabPosition;

    public MainTabsListener(Fragment fragment, int tab_position) {
        this.fragment = fragment;
        TabPosition = tab_position;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        CurrentFragment = fragment;
        CurrentTabSelectedPos = TabPosition;

        /**
         * This is a work-around for Issue 42601
         * https://code.google.com/p/android/issues/detail?id=42601
         * 
         * The method getChildFragmentManager() does not clear up
         * when the Fragment is detached.
         */
        if( fragment instanceof FileLoaderFragment ){
            fragment = reinstatiateFileLoaderFragment();
        }

        ft.replace(R.id.fragment_container, fragment);

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

}

Solution 3

sadly, it's a bug of support v4, still there :(

When you choose other Fragment via Navigation Drawer or other thing like it, the fragment which has sub-fragments is detached. So those sub-fragments' fragmentManager(getChildFragmentManager()) is no longer exist. while those fragments return, error occurred. Bomb!

Obviously, support v4 should clean mChildFragmentManager in onDetach(), but it didn't, so we must depend on ourselves. such as following codes in the fragment which has sub-fragments:

@Override
    public void onDetach() {
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        super.onDetach();
    }

Everything will be OK, have a good day :)

Solution 4

I have the same problem.

In an activity, i have 3 bouttons to switch fragment with transaction.replace(...)

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_tablet_paneau, mLigneMessageFragment);

One of this fragment contain a ViewPage with a custom FragmentPagerAdapter. Therefore, i must do getChildFragmentManager(), to alowed nested Fragments.

the constructor is here:

public LignePagerAdapter(Fragment ligneMessageTabletFragment) {
        super(ligneMessageTabletFragment.getChildFragmentManager());
    }

So i have the same error: The first show of this fragment wrorks, but when i show other fragment and go back on this one, i get this exception:

02-26 11:57:50.798: D/ACRA(776): Wait for Toast + worker ended. Kill Application ? true
02-26 11:57:50.798: E/AndroidRuntime(776): FATAL EXCEPTION: main
02-26 11:57:50.798: E/AndroidRuntime(776): java.lang.IllegalStateException: No activity
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.handleCallback(Handler.java:587)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.dispatchMessage(Handler.java:92)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Looper.loop(Looper.java:132)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.app.ActivityThread.main(ActivityThread.java:4126)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invokeNative(Native Method)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invoke(Method.java:491)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
02-26 11:57:50.798: E/AndroidRuntime(776):  at dalvik.system.NativeStart.main(Native Method)
02-26 11:57:52.818: I/dalvikvm(776): threadid=4: reacting to signal 3
02-26 11:57:52.818: I/dalvikvm(776): Wrote stack traces to '/data/anr/traces.txt'

So instead of put the same instance of fragment, i can re-create this so it fix the problem, but i seem not efficient.

transaction.replace(R.id.layout_tablet_paneau, LigneMessageTabletFragment.newInstance());

Solution 5

may your error is android.view.InflateException?

if so,you should inflate Fragment dynamically ,don't use XML layout.

and, you should not target fragment which is defined XML Layout to Fragment Transaction.

Share:
15,993
user1743524
Author by

user1743524

Updated on June 02, 2022

Comments

  • user1743524
    user1743524 almost 2 years

    I am getting a very puzzling bug that I have no idea how to even begin working through.

    I have a simple app with one activity, the views are implemented with Fragments. One of the fragments has a ViewPager inside of it; so I decided I that I wanted to use the getChildFragmentManager class of the v4 support library. I also had to use ActionBarSherlock, which caused a problem, because it does not ship with the v11 of the v4 library.

    I fixed this by replacing the v4 support library in ABS with the v11 library, and everything compiled and appeared to be working, including the ViewPager.

    Here is the strange part:

    The first time the fragment with the ViewPager opens, it works properly; but the SECOND time it is navigated to, the app crashes, giving a useless stack trace. From debugging, I discovered that the problem was with the FragmentManager returned by getChildFragmentManager; it throws the No Activity error.

    Does anybody have any idea what could be causing this?

    I will post code that you think is relevant.

    Thank you, David

  • user1743524
    user1743524 about 11 years
    no, that wasn't the error. I did fix it temporarily, instead of doing a replace I'm hiding it and showing it. It is not ideal because this method can cause problems on configuration changes.
  • ericosg
    ericosg over 10 years
    I extended my Fragments with this and works like a charm. Solved many issues I have had for so long! well done.
  • Rick Royd Aban
    Rick Royd Aban almost 10 years
    This SHOULD BE the answer :)
  • gaurav414u
    gaurav414u almost 10 years
    Hi... its not working for me.. my code is here: github.com/gbhola-bst/FragmentsTesting
  • gaurav414u
    gaurav414u almost 10 years
    when I go back to the pagerFragment (fragment containing viewPager), I am not able to get any view. And if I use your code, It gives an exception.
  • Kevin Lam
    Kevin Lam almost 10 years
    I was able to navigate to/from the fragment without crashing, but using the back button and then navigating to it again caused the crash. Changing all my fragments to extend from this class instead fixed the issue. So I guess the implementation hasn't been fixed yet.
  • Milaaaad
    Milaaaad over 8 years
    thanks for you it worked for me i have problem with this