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

Android WindowManager$BadTokenException异常:Dialog使用合理性问询

解决android.view.WindowManager$BadTokenException:token null无效问题

问题核心分析

从异常调用栈可以明确:触发报错的并非你自定义的Dialog,而是系统内置的FloatingActionMode(即长按文本等操作弹出的悬浮工具栏)。该组件尝试显示时,对应的Activity窗口已无效,导致WindowManager无法添加窗口。

你当前仅用isFinishing判断存在局限性,以下场景会导致Activity窗口失效但isFinishing未触发:

  • Activity已进入onDestroy阶段,但生命周期状态标记未及时更新
  • 内存不足时Activity被系统回收,代码仍持有引用并触发UI操作
  • 异步回调触发时,Activity已退至后台,窗口token已失效

你的Dialog代码优化建议

虽然当前异常与Dialog无关,但你的showDialog方法可优化以规避同类问题:

  • 结合isDestroyed()(API 17+)覆盖更多销毁场景:
    fun showDialog(title: String, contents: String) {
        if (!isFinishing && !isDestroyed()) {
            val dialog = Dialog(this)
            // 绑定Dialog到当前Activity,确保生命周期同步
            dialog.setOwnerActivity(this)
            dialog.show()
        }
    }
    
  • 若showDialog在异步回调中调用,需额外判断Activity可见性:
    if (!isFinishing && !isDestroyed() && isVisible) {
        // 执行Dialog显示逻辑
    }
    

针对FloatingActionMode异常的解决方案

根据调用栈,需从系统ActionMode的启动逻辑入手:

  1. 全局拦截无效状态下的ActionMode启动:在BaseActivity中重写相关方法:
    override fun startActionMode(callback: ActionMode.Callback): ActionMode? {
        if (!isFinishing && !isDestroyed() && window.decorView.isAttachedToWindow) {
            return super.startActionMode(callback)
        }
        return null
    }
    
    override fun startActionMode(callback: ActionMode.Callback, type: Int): ActionMode? {
        if (!isFinishing && !isDestroyed() && window.decorView.isAttachedToWindow) {
            return super.startActionMode(callback, type)
        }
        return null
    }
    
  2. 拦截触发ActionMode的用户操作:对页面中可触发长按选中的视图(如TextView、列表项),在事件回调中先判断Activity状态:
    someTextView.setOnLongClickListener {
        if (!isFinishing && !isDestroyed()) {
            // 处理长按逻辑
            true
        } else {
            false
        }
    }
    

总结

  • 当前异常由系统FloatingActionMode触发,而非自定义Dialog,但Dialog的状态判断逻辑可优化
  • 结合isFinishing、isDestroyed()和window.decorView.isAttachedToWindow三个条件,能更精准判断Activity窗口有效性
  • 重写Activity的startActionMode方法,从源头拦截无效状态下的系统工具栏启动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:02:37