If you've already tried both coroutine channel and Jetpack's LiveData, you will find that coroutine channel is more robust and flexible than LiveData, but it lacks of handling Android's lifecycle.
This library aims to make coroutine channel aware with Android's lifecycle, especially acting like LiveData's behavior.
// with LiveData
val liveData: LiveData<Int> = TODO()
liveData.observe(lifecycleOwner, Observer { value: Int? ->
if (value != null) {
// consume value here
}
})
// with channel
val receiveChannel: ReceiveChannel<Int> = TODO()
launch(UI) {
receiveChannel.withLifecycle(lifecycleOwner).consumeEach { value: Int ->
// value always non-null, consume it here
}
}
Now you can use withLifecycle
extension to convert your channel to "lifecycle-aware channel":
- This channel won't notify new value when
lifecycleOwner
is inactive (e.g Activity/Fragment paused) - Latest value will deliver when
lifecycleOwner
back toRESUMED
state. - Auto
cancel()
whenlifecycleOwner
goes toDESTROYED
state, no more worry about memory leak
With LiveData
, you can call removeObserver(observer)
or removeObservers(lifecycleOwner)
.
With coroutine channel, we have various ways to stop receive update:
- Cancel the job of coroutine context
- Cancel the channel returned by method
withLifecycle
Note: cancel this chanel doesn't cancel thereceiveChannel
- Cancel the
receiveChannel
With LiveData
, you can call observe()
method multiple time, then all observers will receive the same update.
With coroutine channel, it depends on which type of channel you are using:
- If you want each value only consume only one time, by one observer. Use
Channel()
- If you want all observer receive same update. Use
BroadcastChannel()
With LiveData
, you can't observe data on background thread directly.
With coroutine channel, this is much more flexible, just consume our channel using other dispatcher in coroutine context, such as CommonPool
.
You can inherit LiveData
class to take advantage of method onActive
and onInactive
, for instance when using with Room,
you can stop listen database changes when LiveData
become inactive.
Alternative class available in this library is ColdBroadcastChannel
, example usage:
val coldBroadcastChannel = object : ColdBroadcastChannel<Model>(Channel.CONFLATED) {
var job: Job? = null
override fun onBecomeActive() {
job = Job()
launch(parent = job) {
database.observeChange {
send(database.query())
}
}
}
override fun onBecomeInactive() {
job.cancel()
}
}
// usage
launch(UI) {
coldBroadcastChannel.openSubscription().consumeEach {
// stuff
}
// or open subscription with lifecycle-aware
coldBroadcastChannel.openSubscription(lifecycleOwner).consumeEach {
// stuff, it works like method withLifecycle
}
}
implementation "com.ymusicapp.coroutines:channel-lifecycle:<latest-version>"