【问题标题】:IllegalStateException on AsyncTask [duplicate]AsyncTask 上的 IllegalStateException [重复]
【发布时间】:2017-05-04 07:50:15
【问题描述】:

在收到来自 AsyncTask 的响应后尝试替换片段时出现以下错误:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

问题是,我在通过 Android Studio 重新启动我的应用程序时随机收到此错误。在简化版本中,我的活动包含 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();
}

这个异常如此随机发生的原因是什么?

【问题讨论】:

    标签: android android-asynctask illegalstateexception


    【解决方案1】:

    您应该在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 开始添加,也可以用于相同目的。

    【讨论】:

    • 从 API 26 开始,您也许可以调用 fragment.isStateSaved() 而不是自己保持状态。
    • @StephenM 太好了。让我研究一下这种方法并更新答案。感谢您提供宝贵的信息
    • 我认为当前的答案对于在 API 26 之前运行的人很有用。
    • @StephenM 是的,正确。请查看更新的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 2014-08-04
    • 2014-03-28
    • 2012-05-09
    • 2016-10-26
    • 2015-04-30
    • 2021-05-24
    • 1970-01-01
    相关资源
    最近更新 更多