Issue
I'm getting a following error when trying to replace a fragment upon receiving a response from AsyncTask:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
The thing is, I get this error randomly upon restarting my app through Android Studio. In a simplified version my activity contains 4 key methods (onCreate, taskCompleted, parseJSON and fragmentReplace), that determine which fragment should the user see at the start:
private AsyncTask mMyTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyTask = new AsyncTask(this, this);
mMyTask.executeTaskCall("check_user");
}
@Override
public void taskCompleted(String results) {
try {
JSONObject jsonBody = new JSONObject(results);
parseJSON(jsonBody);
}
catch (JSONException je){
}
}
private void parseJSON(JSONObject jsonBody) throws JSONException {
boolean userActive = jsonBody.getBoolean("result");
if (userActive){
fragmentReplace(new FirstFragment(), "FirstFragment");
}
else {
fragmentReplace(new SecondFragment(), "SecondFragment");
}
}
public void fragmentReplace(Fragment fragment, String fragmentTag){
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.layout_container, fragment, fragmentTag)
.commit();
}
What is the reason of this exception happening so random?
Solution
You should read WeakReference solution (or may be other also) at java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState.
There is one alternate solution for this problem. Using flag you can handle it, like below
/**
* Flag to avoid "java.lang.IllegalStateException: Can not perform this action after
* onSaveInstanceState". Avoid Fragment transaction until onRestoreInstanceState or onResume
* gets called.
*/
private boolean isOnSaveInstanceStateCalled = false;
@Override
public void onRestoreInstanceState(final Bundle bundle) {
.....
isOnSaveInstanceStateCalled = false;
.....
}
@Override
public void onSaveInstanceState(final Bundle outState) {
.....
isOnSaveInstanceStateCalled = true;
.....
}
@Override
public void onResume() {
super.onResume();
isOnSaveInstanceStateCalled = false;
.....
}
And you can check this boolean
value while doing fragment transaction.
private void fragmentReplace(Fragment fragment, String fragmentTag){
if (!isOnSaveInstanceStateCalled) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.layout_container, fragment, fragmentTag)
.commit();
}
}
Update for API 26.1+ (contributed by Stephen M)
Fragment.isStateSaved() has been added since 26.1.0, which can also be used for same purpose.
Answered By - Pankaj Kumar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.