You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切换主题后在Fragment调用recreate()重建Activity崩溃问题

解决调用activity.recreate()导致MaterialDialog崩溃的问题

这个问题我之前也踩过坑!核心原因是你在选择主题后立刻调用activity.recreate(),导致Activity还没等BottomSheet Dialog完全关闭就开始销毁重建——Dialog后续执行dismiss逻辑时,发现它依附的Activity DecorView已经脱离了WindowManager,所以抛出了那个异常。

两种可行的解决方案:

方案1:延迟调用recreate(),给Dialog足够时间完成关闭

在选择主题后先手动关闭Dialog,然后延迟一小段时间再触发Activity重建,确保Dialog的View已经完全从WindowManager移除:

MaterialDialog(context, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
    listItems(R.array.skin) { _, index, text ->
        Prefs(context).setSkin(index)
        // 先关闭Dialog
        dismiss()
        // 延迟300ms执行重建,足够覆盖Dialog的关闭动画时长
        Handler(Looper.getMainLooper()).postDelayed({
            // 用?.避免Activity为空的情况
            activity?.recreate()
        }, 300)
    }
    positiveButton(R.string.select_theme)
    negativeButton(R.string.NegativeButton)
}

方案2:监听Dialog的onDismiss事件,确保完全关闭后再重建

这种方法更可靠,直接在Dialog关闭的回调里执行Activity重建,能精准把握时机:

val themeDialog = MaterialDialog(context, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
    listItems(R.array.skin) { _, index, text ->
        Prefs(context).setSkin(index)
        // 选择后关闭Dialog
        dismiss()
    }
    positiveButton(R.string.select_theme)
    negativeButton(R.string.NegativeButton)
}

// 监听Dialog关闭事件,此时再重建Activity
themeDialog.setOnDismissListener {
    activity?.recreate()
}

额外注意事项:

  • 一定要用activity?.recreate()而不是直接activity.recreate(),避免Fragment已经脱离Activity时出现空指针异常。
  • 如果你的项目用了Coroutines,也可以用delay(300)替代Handler,逻辑是一样的,只要保证Dialog完成关闭流程再触发重建就行。

内容的提问来源于stack exchange,提问作者davod kh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:22:34