屏幕关闭时 DialogFragment IllegalStateException

DialogFragment IllegalStateException when screen goes off

首先,我已经阅读了数十个 SO 问题并阅读了 Alex Lockwood 撰写的关于 IllegalStateException 与片段事务相关的问题的优秀 post:https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html - tl;dr 我已经完成作业了

但是我在任何地方都找不到的是 IllegalStateException 屏幕关闭时的问题,我们正在尝试提交片段事务 - 在我的例子中显示 DialogFragment

我的应用程序中真正发生的事情是对其他 activity 结果作出反应,然后显示 DialogFragment正如许多 SO 用户所建议的那样,我没有显示来自 onActivityResult 的对话框,而是来自 onPostResume 的对话框(我也尝试过使用 onResumeFragments 简化代码看起来像这样

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    Timber.i("${this::class.java.simpleName} onActivityResult")
    activityResult = ActivityResult(this::class, requestCode, resultCode, data)
}

override fun onPostResume() {
    super.onPostResume()
    Timber.i("${this::class.java.simpleName} onPostResume")
    activityResult?.let { ActivityResultRepository.resultsSubject.onNext(it) }
}

override fun onResumeFragments() {
    super.onResumeFragments()
    Timber.i("${this::class.java.simpleName} onResumeFragments")
}

我无法在我的设备 (Mate 20 pro) 或模拟器上重现异常,但我收到了我应用程序用户的崩溃报告(0.5% 的用户受影响)

我的假设是,我的应用试图在屏幕关闭后显示一个对话框。屏幕关闭是导致调用 onSaveInstanceState 方法的任意事件,它可以在我的 onPostResume 方法之前调用。 但这只是我的假设!,也许还有其他原因导致异常

有没有人遇到过类似的问题并且设法解决了?我知道我可以使用 commitAllowingStateLoss 但首先 - DialogFragmentshow 方法不允许这样做,必须使用 FragmentManager 手动显示对话框(不要知道是否有任何影响),其次 commitAllowingStateLoss 通常是一件坏事

我正在添加崩溃报告,尽管每个人都已经在某个地方看到了它:)

Caused by java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
       at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053)
       at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079)
       at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678)
       at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632)
       at android.support.v4.app.DialogFragment.show(DialogFragment.java:143)

Activity class 有方法 isFinishing()link to method。您可以轻松查看:

if (!this.isFinishing)
    loadingDialog.show()

上面的示例是打开普通对话框,但您可以将其与 DialogFragment 一起使用。

这种情况经常发生。 Activity 未处于显示对话框的正确状态。你可以用这个来保护自己:

if (!isFinishing() && !isDestroyed()) {
    dialog.show();
}

我已经接受了@MatPag 的回答,虽然我最终得到了不同的解决方案,所以我发布了它,也许它会对某人有所帮助

在我的场景中,我不关心 savedInstanceState - 当 Android 重新创建它时显示 activity 的初始状态对我来说完全没问题,所以我将 null 传递给父级 onCreate方法:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(null) 
}

稍后,在显示对话框时,我捕获了可能抛出的 IllegalStateException,我为此创建了辅助方法:

private fun DialogFragment.showAllowingStateLoss(manager: FragmentManager?, tag: String) {
    try {
        this.show(manager, tag)
    } catch (e: IllegalStateException) {
        // no-op
    }
}