Launch not executing when called inside a coroutinescope

Viewed 2837

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 Answers

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.

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