ritesh
06/27/2022, 8:11 PMval channel = Channel<Boolen>
which emit a event when certain action happens and in the consumer application, i have this code sitting there in BaseActivity
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
if(AuthSDK.channel.receive){
// logout from app
}
}
}
It works great, i was wondering if it's the correct way of doing it or if there's a better solution in co-routine stream world.
• Reason why i didn't go with SharedFlow
- events can be lost when producer produces but consumer moves to STOPPED state.
• Current channel i am using is RENDEZVOUS
channels, in this scenario, there is a guarantee for my event to be received and emitted, irrespective of lifecycle changes.
• I realised instead of receive
, consumeAsFlow
or receiveAsFlow
can be used. As this is one-off event does it matter if don't.
• Both sender and receiver channel co-routines are on main thread, that also means, both send
and receive
will be in suspended state. Is it a concern, is there a trade-off in doing so.ritesh
06/27/2022, 8:38 PMrepeatOnLifecycle(Lifecycle.State.STARTED)
invoked late, as it waits for the lifecycle to be in STARTED
state from STOPPED
state and now, it looks like
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
if(AuthSDK.channel.receive){
// logout from app
}
}
}
Nick Allen
06/28/2022, 5:38 PM• Reason why i didn't go withNot if you leverage the replay cache. For this scenario, I'd probably just use a StateFlow. Whether we should be logged in or not seems like state to me. StateFlow is basically just SharedFlow with replay=1 (and dedupping behavior). You won't miss the event either way.- events can be lost when producer produces but consumer moves to STOPPED state.SharedFlow
• Current channel i am using ischannels, in this scenario, there is a guarantee for my event to be received and emitted, irrespective of lifecycle changes.RENDEZVOUS
RENDEZVOUS
is not like CoroutineStart.Atomic
. The Activity could be destroyed between receive being scheduled and receive actually resuming. In this case, the item is dropped. This is part of the "Prompt cancellation guarantee" described in Channel.
If you want this to happen "irrespective of lifecycle changes" then why are you using repeatOnLifecycle
?
• Both sender and receiver channel co-routines are on main thread, that also means, bothProducer and consumer sharing a thread only causes problems if you block. Coroutines are designed to share a single thread without issues as long as you are suspending, not blocking. Actually,andsend
will be in suspended state. Is it a concern, is there a trade-off in doing so.receive
send
is unlikely to ever suspend. It'll see there's a receiver and tell it to resume, which will schedule receive to pick up where it left off. Even with Main.immediate
, I don't think it'll resume immediately since you are calling send
so you are already in a coroutine.ritesh
06/29/2022, 7:04 AMStateFlow
but it leverages replay cache, as in it will keep the last item always in the cache (as you mentioned a special case of sharedFlow with replayCache set to 1) and any new collector will get it. It could be solved, by changing it's state once i consume it. But, i want to avoid this solution, where theres a two way communication to make sure that the event is received only once, by notifying that event is consumed.
The Activity could be destroyed between receive being scheduled and receive actually resuming. In this case, the item is dropped. This is part of the "Prompt cancellation guarantee" described inI came across this discussion - i believe both send and receive if posted on
Main.Immediate
the event will be collected, irrespective of prompt cancellation
https://github.com/Kotlin/kotlinx.coroutines/issues/2886#issuecomment-901188295
If you want this to happen "irrespective of lifecycle changes" then why are you usingThanks for pointing it out. I agree?repeatOnLifecycle
repeatOnLifecycle
can be avoided.