AsyncTask 上的 IllegalStateException
IllegalStateException on AsyncTask
在收到 AsyncTask 的响应后尝试替换片段时出现以下错误:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
问题是,我在通过 Android Studio 重新启动我的应用程序时随机收到此错误。在简化版本中,我的 activity 包含 4 个关键方法(onCreate、taskCompleted、parseJSON 和 fragmentReplace),用于确定用户应该在开始时看到哪个片段:
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();
}
这个异常随机发生的原因是什么?
您应该在 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 阅读 WeakReference 解决方案(或者也可能是其他解决方案)。
这个问题有一个替代解决方案。使用标志你可以处理它,如下所示
/**
* 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;
.....
}
并且您可以在进行片段交易时查看此boolean
值。
private void fragmentReplace(Fragment fragment, String fragmentTag){
if (!isOnSaveInstanceStateCalled) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.layout_container, fragment, fragmentTag)
.commit();
}
}
API 26.1+ 的更新(由 Stephen M 贡献)
Fragment.isStateSaved()是从26.1.0开始添加的,也可以用于同样的目的。
在收到 AsyncTask 的响应后尝试替换片段时出现以下错误:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
问题是,我在通过 Android Studio 重新启动我的应用程序时随机收到此错误。在简化版本中,我的 activity 包含 4 个关键方法(onCreate、taskCompleted、parseJSON 和 fragmentReplace),用于确定用户应该在开始时看到哪个片段:
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();
}
这个异常随机发生的原因是什么?
您应该在 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 阅读 WeakReference 解决方案(或者也可能是其他解决方案)。
这个问题有一个替代解决方案。使用标志你可以处理它,如下所示
/**
* 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;
.....
}
并且您可以在进行片段交易时查看此boolean
值。
private void fragmentReplace(Fragment fragment, String fragmentTag){
if (!isOnSaveInstanceStateCalled) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.layout_container, fragment, fragmentTag)
.commit();
}
}
API 26.1+ 的更新(由 Stephen M 贡献)
Fragment.isStateSaved()是从26.1.0开始添加的,也可以用于同样的目的。