Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IllegalStateException: Fragment <ThisFragment> is not currently in the FragmentManager

I have trouble of tracing the cause of the crash in my app. I have a fragment that displays a ListView, I also have SlidingMenu for a search field. And when I search, the ListView items are repopulated basing from the search results. Now, my app crashes when I try to open a ListView item from the new populated result.

The exception is triggered here:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mContent", mContent); //Exception made here
}

Is this because of the support library? How do I resolve this?

EDIT:

Here's the stack trace:

02-05 12:51:53.941: E/AndroidRuntime(11638): FATAL EXCEPTION: main
02-05 12:51:53.941: E/AndroidRuntime(11638): java.lang.IllegalStateException: Fragment MyFragment{436749b0} is not currently in the FragmentManager
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.support.v4.app.FragmentManagerImpl.putFragment(FragmentManager.java:546)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.sample.android.app.SearchListActivity.onSaveInstanceState(SearchListActivity.java:118)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.Activity.performSaveInstanceState(Activity.java:1137)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1215)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:2972)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3031)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.access$900(ActivityThread.java:138)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.os.Looper.loop(Looper.java:213)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at android.app.ActivityThread.main(ActivityThread.java:4787)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at java.lang.reflect.Method.invokeNative(Native Method)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at java.lang.reflect.Method.invoke(Method.java:511)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
02-05 12:51:53.941: E/AndroidRuntime(11638):    at dalvik.system.NativeStart.main(Native Method)

EDIT 2: Here's my Activity:

private Fragment mFragment;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            ..........

    params = new Bundle();
    params.putInt("id", id);

    // set the Above View Fragment
    if (savedInstanceState != null)
        mFragment = getSupportFragmentManager().getFragment(
                savedInstanceState, "mFragment");
    else {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        SampleListFragment fragment = new SampleListFragment();
        fragment.setArguments(params);
        fragmentTransaction.add(R.id.list_fragment, fragment);
        fragmentTransaction.commit();
    }

    if (mFragment == null) {
        mFragment = new SampleListFragment();
        mFragment.setArguments(params);
    }
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.list_fragment, mFragment).commit();

    // set the Behind View Fragment
    Fragment searchFragment = new SampleSearchFragment();
    searchFragment.setArguments(params);

    getSupportFragmentManager().beginTransaction()
            .replace(R.id.activity_search, searchFragment)
            .commit();
}


@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mFragment",
            mFragment);
}

And in my SampleListFragment, I have this method:

public static boolean isNetworkAvailable(Activity activity) {
    ConnectivityManager connectivity = (ConnectivityManager) activity
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivity == null) {
        return false;
    } else {
        NetworkInfo[] info = connectivity.getAllNetworkInfo();
        if (info != null) {
            for (int i = 0; i < info.length; i++) {
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
    }
    return false;
}

Inside of Asynctask:

..........
@Override
protected void onPostExecute(String result) {
    super.onPostExecute(null);

    if (null != pDialog && pDialog.isShowing()) {
        pDialog.dismiss();
    }

    if (isNetworkAvailable(getActivity())) { //Triggered NPE

From here, how do I know if getActivity() is now attached to the parent activity before calling it?

like image 509
Compaq LE2202x Avatar asked Feb 05 '14 03:02

Compaq LE2202x


4 Answers

Before saving the fragment in onSaveInstanceState make sure to check if fragment is added to fragment manager

@Override 
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (mFragment.isAdded()){
        getSupportFragmentManager().putFragment(outState, "mFragment", mFragment); 
    }
} 
like image 72
Felipe Conde Avatar answered Nov 09 '22 01:11

Felipe Conde


I am also facing same problem. WHEN I tried to put fragment in bundleState in

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    getSupportFragmentManager().putFragment(outState, "mContent",   mContent); //Exception made here
}

I checked implementation of putFragment() method in FragmentManager. It is like

 @Override
 public void putFragment(Bundle bundle, String key, Fragment fragment) {
    if (fragment.mIndex < 0) {
         throwException(new IllegalStateException("Fragment " + fragment
                    + " is not currently in the FragmentManager"));
    }
    bundle.putInt(key, fragment.mIndex);
  }

where mIndex is fragment index into active fragment array. So if mIndex < 0 that means fragment is not currently active. So as @FelipeConde suggested checking mFragment.isAdded() could be the best solution.

like image 39
Amol Desai Avatar answered Nov 09 '22 00:11

Amol Desai


In my case, I had 2 fragments (PopularMoviesFragment & TopRatedMoviesFragement), PopularMoviesFragment was populated in onCreate of the Activity and the other will be populated with a click of BottomNavigationView.

So When I open the app and without clicking the BottomNavigationView if I minimize (or navigate to some other app) I got this Exception

java.lang.IllegalStateException: Fragment TopRatedMoviesFragement{79d8905} is not currently in the FragmentManager

My code in onCreate() was

if (currentSelectedbottomNavigation.equals(FRAGMENT_1)) {

        fragmentManager.beginTransaction()
                .replace(R.id.containerw, fragment_1, FRAGMENT_1)
                .addToBackStack(null)
                .commit();
    }else if (currentSelectedbottomNavigation.equals(FRAGMENT_2)){   

        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment_2, FRAGMENT_2)
                .addToBackStack(null)
                .commit();
    }

Hence what I did is just added TopRatedMoviesFragement and then replaced it by PopularMoviesFragment, as shown in below code.

if (currentSelectedbottomNavigation.equals(FRAGMENT_1)) {

        fragmentManager.beginTransaction()
                .add(R.id.container, fragment_2, FRAGMENT_2)
                // Its been added to avoid Fragment is not currently in the FragmentManager
                .replace(R.id.container, fragment_1, FRAGMENT_1)
                .addToBackStack(null)
                .commit();
    }else if (currentSelectedbottomNavigation.equals(FRAGMENT_2)){  

        fragmentManager.beginTransaction()
                .replace(R.id.container, fragment_2, FRAGMENT_2)
                .addToBackStack(null)
                .commit();
    }

Hope this also helps. :)

like image 2
Kavin Raju S Avatar answered Nov 09 '22 02:11

Kavin Raju S


Recently, I've faced the same problem . In my case, I forgot to set mFragment when activity's onBackPressed() is called. That is, when user navigates through A -> B -> C, mFragment is changing accordingly to A, then B, and finally C. However, when back is pressed the current fragment is reversely changing to B, then A, but mFragment is still C. Thus, during onSaveInstanceState, activity tries to save C which is not in the FragmentManager anymore.

The main point is, you are probably changing (adding or removing) current [displayed] fragment without appropriately changing mFragment.

like image 1
Esmailian Avatar answered Nov 09 '22 00:11

Esmailian