I have an app in the market and I get the following exception:
Fatal Exception: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1343)
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1361)
at android.app.BackStackRecord.commitInternal(BackStackRecord.java:729)
at android.app.BackStackRecord.commit(BackStackRecord.java:705)
at com.mysupercoolapp.ui.fragments.ResultFragment$2.onItemClick(ResultFragment.java:139)
at android.widget.AdapterView.performItemClick(AdapterView.java:339)
at android.widget.AbsListView.performItemClick(AbsListView.java:1544)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3721)
at android.widget.AbsListView$3.run(AbsListView.java:5660)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
I already read most of the topics regarding this issue but I do not know what I am doing wrong in my code. It's not like I am replacing a Fragment in the onResume method. I am also not caching a FragmentTransaction instance. I replace the Fragment when an user clicks an item in a ListView.
My Fragment's code workflow is the following
OnCreateView > executes AsyncTask to load some items from the database > onPostExecute calls a method which sets the adapter for the ListView and it adds an OnItemClickListener so when the user presses an item in the ListView it opens up the item in an other Fragment.
Here's the code for it:
@Override
protected void onPostExecute(ResultAdapter adapter) {
// post execute in AsyncTask
setListAdapter(adapter);
}
public void setListAdapter(final ResultAdapter adapter) {
if (adapter != null && isAdded()) {
resultList.setAdapter(adapter);
resultList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
SomeFragment fragment = new SomeFragment();
ft.replace(R.id.content_frame, fragment, "main_fragment");
ft.addToBackStack(null);
ft.commit();
}
});
adapter.notifyDataSetChanged();
}
}
Is there a better solution than calling commitAllowingStateLoss()
or overriding onSaveInstanceState()
?
P.S.: I am targetting API > 14 and am using the standard android.app.FragmentTransaction
package.
This problem will occur when onPostExecute()
is called when the application is minimized, especially when onPostExecute()
is called after the onSaveInstanceState()
method of the activity is called.
If you are worried about the state loss, then I suggest that you cancel your AsyncTask
when the user has minimized the application, (probably in the onStop()
method). Then in your onPostExecute()
, call setListAdapter(adapter)
only if the AsyncTask
is not cancelled. This would ensure that you don't end up setting the adapter after the onSaveInstanceState()
is called.
More info on how to accomplish this is here: https://stackoverflow.com/a/12342937/4747587