Android 在coroutinescope内调用时不执行启动

Android 在coroutinescope内调用时不执行启动,android,kotlin,kotlin-coroutines,android-snackbar,Android,Kotlin,Kotlin Coroutines,Android Snackbar,我在一个协同例程中调用launch,但它不执行。Snackbar操作侦听器正在执行,但由于某些原因启动块未执行 CoroutineScope(Dispatchers.Main)。启动{ val scope=this val mn=snackbarManager(R.id.root); Snackbar.make(mn.container,R.string.recpt\u已删除,Snackbar.LENGTH\u LONG) .setAction(R.string.undo){ scope.lau

我在一个协同例程中调用launch,但它不执行。Snackbar操作侦听器正在执行,但由于某些原因启动块未执行

CoroutineScope(Dispatchers.Main)。启动{
val scope=this
val mn=snackbarManager(R.id.root);
Snackbar.make(mn.container,R.string.recpt\u已删除,Snackbar.LENGTH\u LONG)
.setAction(R.string.undo){
scope.launch{**//未执行**
Toast.makeText(requireContext(),“提交”,Toast.LENGTH\u LONG.show())
Log.d(“提交”、“调用提交”)
}
}
.show()
}

在Snackbar action listener中使用的
作用域与调用第一个
启动
函数时使用的作用域不同。要解决此问题,您可以参考主
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
时,当外部协同程序完成时,此
范围
变为已完成。当您在
Snackbar
操作侦听器中启动内部协同程序时,
范围
已处于完成状态。我们无法使用
CoroutineScope
完成状态启动协同程序。

对于第二个
范围
启动
您应该使用
调度程序。Main
,因为:

Main
coroutine
dispatcher
,仅限于使用UI对象操作的主线程。通常,此类
调度程序是单线程的。

第一种方式:

   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()
    }
然后,您应该将代码更改为:

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()
    }
第二种方式:

   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()
    }

第一个
CoroutineScope
也使用
Dispatchers.Main
,因此这不是问题所在。不,它不使用
Dispatchers.Main
,如果使用它,它工作得很好,通过更新我的答案,它将在第二个作用域中再次使用
Dispatchers.Main
。@miladsalimi不应该执行launch block,无论使用哪个作用域?我的理解是,无论使用哪个作用域,launch都应该始终执行。我的理解错了吗?