Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 垃圾收集挂起的协同程序任务_Kotlin_Coroutine - Fatal编程技术网

Kotlin 垃圾收集挂起的协同程序任务

Kotlin 垃圾收集挂起的协同程序任务,kotlin,coroutine,Kotlin,Coroutine,我使用kotlin协同程序显示确认对话框并处理结果 suspend fun showConfirmationDialog() = suspendCancellableCoroutine<Boolean> { cont -> val dialog = AlertDialog.Builder(this) .setMessage("Are you sure?") .setPositiveButton("Yes", { _, _

我使用kotlin协同程序显示确认对话框并处理结果

suspend fun showConfirmationDialog() = suspendCancellableCoroutine<Boolean> { cont ->
    val dialog = AlertDialog.Builder(this)
            .setMessage("Are you sure?")
            .setPositiveButton("Yes", { _, _ -> cont.resume(true) })
            .setNegativeButton("No", { _, _ -> cont.resume(false) })
            .setCancelable(true)
            .setOnCancelListener { cont.cancel() }
            .create()

    dialog.show()
    cont.invokeOnCompletion { dialog.dismiss() }
}
suspend-fun-showConfirmationDialog()=suspendcancelablecoroutine{cont->
val dialog=AlertDialog.Builder(此)
.setMessage(“您确定吗?”)
.setPositiveButton(“是,{{,{->cont.resume(true)})
.setNegativeButton(“否,{{,{->cont.resume(false)})
.setCancelable(真)
.setOnCancelListener{cont.cancel()}
.create()
dialog.show()
cont.invokeOnCompletion{dialog.disease()}
}

但我觉得这段代码容易发生内存泄漏,如果继续操作没有恢复,任务将永远运行。取消任务的正确方法是什么?

这种方法现在已经不常见了,但是如果它对您的程序有意义的话,那也没关系

但是,当您调用
suspendCoroutine
时,必须确保返回的
延续将被恢复。这不仅仅是因为内存泄漏。在
finally
块中可能需要发生各种重要的事情,这些事情只有在
Continuation
恢复时才会运行--释放锁、关闭文件和连接等

如果在对话框构造或显示过程中抛出异常,您的协同程序将不会挂起,因此这已经得到了处理

但是,请确保在继续进行之前,无法关闭对话框。您可能想使用
onDismissListener

另外,我不知道
invokeOnCompletion
方法或
cancelablecontinuation
的扩展。。。确保它是你想要的,否则就不要使用它

我会更直接地处理解雇问题,如下所示:

suspend fun showConfirmationDialog() : Boolean {
    var dialog : Dialog?
    try {
        return suspendCancellableCoroutine<Boolean> { cont ->
            val newDialog = AlertDialog.Builder(context)
                .setMessage("Are you sure?")
                .setPositiveButton("Yes", { _, _ -> cont.resume(true) })
                .setNegativeButton("No", { _, _ -> cont.resume(false) })
                .setCancelable(true)
                .setOnDismissListener { dialog = null;cont.cancel() }
                .create()

            newDialog.show()
            dialog = newDialog
        }
    } finally {
        dialog?.dismiss()
    }
}
showConfirmationDialog():布尔值{
var对话框:对话框?
试一试{
返回SuspendCancelableCoroutine{cont->
val newDialog=AlertDialog.Builder(上下文)
.setMessage(“您确定吗?”)
.setPositiveButton(“是,{{,{->cont.resume(true)})
.setNegativeButton(“否,{{,{->cont.resume(false)})
.setCancelable(真)
.setOnDismissListener{dialog=null;cont.cancel()}
.create()
newDialog.show()
dialog=newDialog
}
}最后{
对话框?.discover()
}
}

为什么不正确地分离关注点?让您的协同程序向您的viewmodel/presenter/无论什么发送信号,弹出通知,让您的UI(活动、片段等)观察该信号,等待UI向视图模型发送另一个带有用户响应的信号,然后让您的viewmodel/presenter/无论什么,将信号再次向下吹向存储库/协同程序所在的任何位置,以便它可以执行它必须执行的操作。你把所有的鸡蛋都放在同一个篮子里。@MartinMarconcini如果你比较这两种方法,上面的解决方案可以简单到'val-answer=fetchNumberFromDialog1()+fetchNumberFromDialog2()vs fetchNumberFromDialog2().observe(a->fetchNumberFromDialog2.observe(b->{})`基本上,有没有一种方法可以在不使用引入嵌套代码级别的回调的情况下观察响应?是否可以只执行input=wait askForInput()在受控范围内启动协同程序,最终可以取消。我认为这不是唯一的选择。在我看来,你只是简单地对其进行语法糖化,以牺牲混合责任为代价。如果你需要标记一个进程,那么你需要一些Mixin类或类似类,甚至一个repo来为你管理它。你的对话框uld由您的演示文稿(viewmodel->fragment/act)处理,这与协同程序完全无关。再说一遍,这只是一个偏好问题。我不会做您正在做的事情,但我不是站在您的立场上:)