https://kotlinlang.org logo
Title
m

miguelsesma

10/11/2019, 9:35 AM
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:
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:
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:
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

streetsofboston

10/11/2019, 11:25 AM
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

miguelsesma

10/11/2019, 11:49 AM
Thanks Anton. I'll give it a read.