首先,我阅读了数十个SO问题,并阅读了Alex Lockwood的精彩文章,内容涉及与片段事务有关的IllegalStateException
问题:https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html- tl; dr完成我的作业
但是我什么都没发现是IllegalStateException
问题,当屏幕关闭并且我们正在尝试执行片段事务时-在我的情况下显示DialogFragment
。
我的应用程序中发生的实际情况是对其他活动结果做出了反应,后来又显示了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
,但首先-show
的{{1}}方法不允许这样做,必须使用DialogFragment
手动显示对话框(不要知道是否有任何暗示),其次FragmentManager
通常是一件坏事
我正在添加崩溃报告,尽管每个人都已经看到它了:)
commitAllowingStateLoss
答案 0 :(得分:0)
活动类具有方法isFinishing()
,link to method。您可以轻松检查:
if (!this.isFinishing)
loadingDialog.show()
上面的示例打开了纯对话框,但是您可以将其与DialogFragment一起使用。
答案 1 :(得分:0)
这种情况经常发生。活动状态不正确,无法显示对话框。您可以通过以下方法来保护自己:
if (!isFinishing() && !isDestroyed()) {
dialog.show();
}
答案 2 :(得分:0)
我已经接受@MatPag答案,但我最终得到了不同的解决方案,所以我要发布它,也许会对某人有所帮助
在我的情况下,我不在乎saveInstanceState-在Android重新创建活动时显示活动的初始状态对我来说是完全可以的,因此我将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
}
}