Launch not executing when called inside a coroutinescope

6.1k views Asked by At

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

There are 2 answers

3
Sergio On BEST ANSWER

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.

3
milad salimi On

For the second scope launch you should use Dispatchers.Main because of :

Main coroutine dispatcher that is confined to the Main thread operating with UI objects. Usually such dispatchers are single-threaded.

FIRST WAY :

Then you should change your code to this :

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

UPDATE :

SECOND WAY:

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