在协程范围内调用时启动不执行
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 状态。我们无法使用 CoroutineScope
和 COMPLETED 状态启动协程。
对于第二个 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()
}
我在协程范围内调用启动,但它没有执行。 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 状态。我们无法使用 CoroutineScope
和 COMPLETED 状态启动协程。
对于第二个 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()
}