在协程范围内调用时启动不执行

Launch not executing when called inside a coroutinescope

我在协程范围内调用启动,但它没有执行。 Snackbar 动作侦听器正在执行,但启动块由于某种原因未执行。

CoroutineScope(Dispatchers.Main).launch {
    val scope = this
    val mn = snackbarManager(R.id.root)
    Snackbar
        .make(mn.container, R.string.recpt_deleted, Snackbar.LENGTH_LONG)
        .setAction(R.string.undo) {
            scope.launch { // not executing
                Toast.makeText(requireContext(),"Committing",Toast.LENGTH_LONG).show()
                Log.d("COMMIT", "calling commit")
            }
        }
        .show()
}

您在 Snackbar 动作侦听器中使用的 scope 与您调用第一个 launch 函数时使用的作用域不同。要解决此问题,您可以参考主要 CoroutineScope:

val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
    // ...
    // in action listener:
    scope.launch { /*...*/ }
}

或者在 Snackbar 动作侦听器中使用另一个 CoroutineScope,例如 lifecycleScope 属性:

lifecycleScope.launch {
    Toast.makeText(requireContext(),"Committing",Toast.LENGTH_LONG).show()
    Log.d("COMMIT", "calling commit")
}

但我认为您的代码有点乱。我认为你应该重新考虑你的方法并且不要使用 CoroutineScope 来显示 Snackbar.

更新:

当您在第一个协程 val scope = this 中初始化 scope 变量时,当外部协程完成时,此 scope 变为 COMPLETED。当您在 Snackbar 动作侦听器中启动内部协程时,scope 已经具有 COMPLETED 状态。我们无法使用 CoroutineScopeCOMPLETED 状态启动协程。

对于第二个 scope launch 你应该使用 Dispatchers.Main 因为 :

Main coroutine dispatcher 仅限于使用 UI 对象运行的主线程。通常这样的dispatchers是single-threaded.

第一种方式:

那么您应该将代码更改为:

CoroutineScope(Dispatchers.Main).launch {
    Snackbar.make(requireView(),"milad", Snackbar.LENGTH_LONG)
        .setAction("clickMe"){
            CoroutineScope(Dispatchers.Main).launch {
                Toast.makeText(requireContext(),"Committing", Toast.LENGTH_LONG).show()
                Log.d("COMMIT", "calling commit")
            }
        }.show()
}

更新:

第二种方式:

   val coro= CoroutineScope(Dispatchers.Main)

    coro.launch {
        Snackbar.make(requireView(),"milad", Snackbar.LENGTH_LONG)
            .setAction("clickMe"){
                coro.launch {
                    Toast.makeText(requireContext(),"Committing", Toast.LENGTH_LONG).show()
                    Log.d("COMMIT", "calling commit")
                }
            }.show()
    }