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

Kotlin协程确认对话框内存泄漏风险及任务取消方案咨询

正确处理Kotlin协程对话框的取消与内存泄漏问题

你担心的内存泄漏风险确实存在,而且你的判断很准确——如果continuation没被正确处理,不仅可能让任务挂起占用资源,还可能引发异常或者内存泄漏。咱们来一步步优化这段代码,解决取消逻辑的问题:

核心优化思路

  • 在尝试恢复continuation前,先检查它是否仍处于活跃状态,避免协程已取消时触发无效操作
  • 确保协程无论以何种方式结束(正常完成、被取消、异常),对话框都能被及时关闭
  • 避免对话框回调持有外部组件引用导致的泄漏

优化后的代码

suspend fun showConfirmationDialog() = suspendCancellableCoroutine<Boolean> { cont ->
    val dialog = AlertDialog.Builder(this)
        .setMessage("Are you sure?")
        .setPositiveButton("Yes") { _, _ ->
            // 只有协程仍活跃时,才恢复结果
            if (cont.isActive) {
                cont.resume(true)
            }
        }
        .setNegativeButton("No") { _, _ ->
            if (cont.isActive) {
                cont.resume(false)
            }
        }
        .setCancelable(true)
        .setOnCancelListener {
            // 用户主动取消对话框时,取消协程
            if (cont.isActive) {
                cont.cancel(CancellationException("Dialog dismissed by user"))
            }
        }
        .create()

    dialog.show()

    // 协程完成(无论成功、取消、异常)时,关闭对话框
    cont.invokeOnCompletion {
        // 确保在主线程操作对话框,避免跨线程问题
        runOnUiThread {
            if (dialog.isShowing) {
                dialog.dismiss()
            }
        }
    }

    // 专门处理协程被外部取消的场景,强化资源清理逻辑
    cont.invokeOnCancellation {
        runOnUiThread {
            dialog.dismiss()
        }
    }
}

关键细节解释

  1. 检查cont.isActive:
    当协程被取消后,continuation的isActive会变为false,此时再调用resume会抛出IllegalStateException。在按钮点击和取消回调中先检查活跃状态,既能避免异常,也能防止无效的状态更新。

  2. 双保险的资源清理:

    • invokeOnCompletion会覆盖协程所有结束场景,确保对话框一定会被关闭,从根源避免内存泄漏。
    • 额外添加invokeOnCancellation是为了更明确地处理外部取消协程的场景,让逻辑更清晰,即使invokeOnCompletion已经覆盖了这个情况,分开处理也能提升代码可读性。
  3. 主线程安全:
    对话框的dismiss()必须在主线程调用,而协程的完成回调可能在后台线程执行。用runOnUiThread(Activity中)或者viewLifecycleOwner.lifecycleScope(Fragment中)包裹对话框操作,能避免跨线程崩溃。

  4. 避免组件引用泄漏:
    如果这段代码写在Activity或Fragment中,要注意AlertDialog.Builder(this)持有组件引用。建议配合viewLifecycleOwner(Fragment)或者在组件销毁时主动取消协程(比如在onDestroy中调用coroutineScope.cancel()),进一步降低泄漏风险。

这样调整后,不管是用户主动取消对话框,还是协程被外部取消,都能保证资源被正确释放,彻底解决你担心的内存泄漏和任务挂起问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 23:38:12