Hello, I have a doubt about channels. I have this ...
# coroutines
m
Hello, I have a doubt about channels. I have this code running flawlessly for receiving live information using websockets with Tinder.Scarlet library and its coroutines adapter:
Copy code
private val job = Job()
    private val coroutineContext = job + Dispatchers.Main
    private val scope: CoroutineScope = CoroutineScope(coroutineContext)

   override fun onResume() {
        super.onResume()
        scope.launch { subscribe() }
    }

    private suspend fun subscribe() {
        dataStore.subscribe()
         val channel: ReceiveChannel = dataStore.receiveMessage()
        for (message in channel) {
            when (message.type) {
                "error" -> textView_scrollable.addTextNl("error: ${message.message}")
                "ticker" -> textView_scrollable.addTextNl("ticker: ${message.sequence}, ${message.productId}, ${message.price}")
            }
        }
    }

    override fun onPause() {
        dataStore.unsubscribe()
        job.cancel()
        super.onPause()
    }
But I have tried the same using
consumeEach
instead the for loop:
Copy code
private suspend fun subscribe() {
       dataStore.subscribe()
        val channel: ReceiveChannel = dataStore.receiveMessage()
       channel.cosumeEach { message ->
           when (message.type) { 
               "error" -> textView_scrollable.addTextNl("error: ${message.message}")
               "ticker" -> textView_scrollable.addTextNl("ticker: ${message.sequence}, ${message.productId}, ${message.price}")
           }
       }
   }
It still works receiving the information, but when I cancel the job I get a
JobCancellationException
.
consumeEach
Documentation says:
Copy code
Performs the given action for each received element and cancels the channel after the execution of the block. If you need to iterate over the channel without consuming it, a regular for loop should be used instead.
I'm not sure what it means with cancels the channel after the execution of the block. Maybe it is related. I have tried other things like
try-finally
,
NonCancellable
,
SupervisorScope
... But if I get rid of the exception I get a memory leak in exchange because the coroutine remains alive after the fragment dies. I know that probably is something I'm understanding badly. But after reading everything I have found, I'm still lost.
s
I'd have to debug your code to really see what's going on. In the meantime, I hope this article I wrote may help you. https://medium.com/@streetsofboston/how-can-we-use-coroutinescopes-in-kotlin-2210695f0e89?sk=f41c033cd023085329c497cb826d66e1
👍🏼 1
m
Thanks Anton. I'll give it a read.