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?
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);
}
}
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.
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. :)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With