Kotlinx.coroutines: Converting channel to LiveData results in IllegalStateException: "ReceiveChannel.consumeAsFlow can be collected just once"

Created on 26 Apr 2020  路  3Comments  路  Source: Kotlin/kotlinx.coroutines

When I use Channel and convert it to Android LiveData by consumeAsFlow().asLiveData() in Android ViewModel like this

class MainViewModel : ViewModel() {
    private val channel = Channel<Int>()
    val channelLiveData = channel.consumeAsFlow().asLiveData()
}

Then subscribe it in the Android Activity's onCreate

viewModel.channelLiveData.observe(this) {
    //...
}

There's an exception raised when I press home button to home screen(Lifecycle stopped) for a few seconds, and then back to app:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.diousk.channellivedataissue, PID: 20520
    java.lang.IllegalStateException: ReceiveChannel.consumeAsFlow can be collected just once
        at kotlinx.coroutines.flow.ChannelAsFlow.markConsumed(Channels.kt:128)
        at kotlinx.coroutines.flow.ChannelAsFlow.collect(Channels.kt:153)
        at androidx.lifecycle.FlowLiveDataConversions$asLiveData$1.invokeSuspend(FlowLiveData.kt:139)

which leads to the app crash

But if I change to BroadcastChannel, the exception does not raise.

How can I just use the normal Channel as LiveData?

Most helpful comment

@elizarov @ashdavies receiveAsFlow did the job! thanks for pointing this out :)

All 3 comments

I'm not sure what you are trying to achieve, but you can use receiveAsFlow operator instead of produceAsFlow. Does it help? What is your use-case? Why you need to convert channel to live data?

LiveData is designed to be used with Android components, ie framework elements that are likely to detach and re-attach, thus LiveData and its upstream components will need to handle cancellation in a way that doesn't prevent re-consumption. As @elizarov mentions, receiveAsFlow is the best option here afaik as it will not cancel the "upstream" Channel on Lifecycle death.

@elizarov @ashdavies receiveAsFlow did the job! thanks for pointing this out :)

Was this page helpful?
0 / 5 - 0 ratings