I'm calling launch inside a coroutinescope but it does not execute. Snackbar action listener is executing but the launch block is not executing for some reason.
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()
}
Inject Dispatchers Don't hardcode Dispatchers when creating new coroutines or calling withContext . This dependency injection pattern makes testing easier as you can replace those dispatchers in unit and instrumentation tests with a test dispatcher to make your tests more deterministic.
CoroutineScopeDefines a scope for new coroutines. Every coroutine builder (like launch, async, etc.) is an extension on CoroutineScope and inherits its coroutineContext to automatically propagate all its elements and cancellation.
The coroutine context includes a coroutine dispatcher (see CoroutineDispatcher) that determines what thread or threads the corresponding coroutine uses for its execution. The coroutine dispatcher can confine coroutine execution to a specific thread, dispatch it to a thread pool, or let it run unconfined.
The easiest way to create a coroutine scope object is by using the CoroutineScope factory function 1. It creates a scope with provided context (and an additional Job for structured concurrency if no job is already part of the context).
The scope
you are using in Snackbar action listener is not the same scope you use to call the first launch
function. To tackle the problem you can make a reference to the main CoroutineScope
:
val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
// ...
// in action listener:
scope.launch { /*...*/ }
}
Or use another CoroutineScope
in Snackbar action listener, for example, lifecycleScope
property:
lifecycleScope.launch {
Toast.makeText(requireContext(),"Committing",Toast.LENGTH_LONG).show()
Log.d("COMMIT", "calling commit")
}
But in my opinion your code is a little bit mess. I think you should reconsider your approach and don't use the CoroutineScope
to show the Snackbar
.
UPDATE:
When you initialize scope
variable in the first coroutine val scope = this
, this scope
becomes COMPLETED when the outer coroutine is finished. When you launch inner coroutine in Snackbar
action listener the scope
already has COMPLETED state. We can't launch a coroutine using CoroutineScope
with COMPLETED state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With