BottomSheetDialogFragment 使用dismiss()出现异常java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
当 BottomSheetDialogFragment 调用 dismiss() 时,如果在调用 onSaveInstanceState() 后立即调用,就会抛出 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 异常。这是由于操作已被 Android 系统禁止,以保护应用程序免受资源损失的风险。
解决方式一
为了避免此异常,您可以将 dismiss() 操作推迟到过渡动画结束后才执行。当 BottomSheetDialogFragment 中的嵌入,EditText 或其它Focusable 类型对话框或 UI 控件时,因为这些控件可能争取了焦点等情碱,而已经跳过 onSaveInstanceState 的处理。为了防止用户体验上的瑕疵,我们可以通过将 dismiss() 操作封装在 Handler 延时运行,以确保安全地使用它:
// 先声明一个 mHandler :
val mHandler = Handler(Looper.getMainLooper())
// 在想要关闭dialog时使用它
mHandler.postDelayed({
dialog?.dismiss()
}, 500)
在上述示例代码中,我们首先定义了一个名为 mHandler 的 Handler 对象,并将主线程的消息循环传递给它。然后,在需要关闭 dialog 时,我们先使用 postDelayed() 方法将 dismiss() 操作延迟 500 毫秒以确保 transition 和其他绘制动作已经完成,最后执行相应的操作。注意不必使用任何记号来取消,因为在指定时间里未能被运行时系统会自动丢弃已经无效的延迟操作。
请注意,使用 Handler 可能会引发内存泄漏问题(尤其是在持续挂起的场景下)。建议您在不再需要时及时清理并释放 MainActivity / Fragment 所持有的 handler对象来避免其产生潜在的问题。
解决方式二
锁定屏幕或旋转屏幕时,窗口操作的一部分(比如 transition)可能会被取消、停顿或重启,导致用户界面卡住或出现竞态条件。可视视觉化变化后的动作(如 dismiss())最好从事务管理中进行
commitNowAllowingStateLoss()
或者
dismissAllowingStateLoss()
替代处理以更好的避免类似情况的发生。
网友评论