https://kotlinlang.org logo
#android
Title
# android
k

KamilH

01/09/2020, 9:57 AM
I have a simple
Flow
wrapper around
LiveData
and I have a problem, because it closes (
invokeOnClose
is called) immediately after first value is emitted by
Observer
.
Copy code
fun <T> LiveData<T>.asFlow(): Flow<T> = channelFlow {
    value?.let { offer(it) }
    val observer = Observer<T> { t -> t?.let(this::offer) }
    observeForever(observer)
    invokeOnClose {
        removeObserver(observer)
    }
}
To be sure my
CoroutineScope
is not causing this cancellation, I run this also in
GlobalScope
and the behaviour was the same. How can I see what is causing cancellation? I analysed stack trace, but I didn’t see anything interesting there.
k

KamilH

01/09/2020, 12:43 PM
Thank you. In a code you posted there is a custom
LiveData
implementation, it have
addObserver
function which is not available in Android’s LiveData even though it can be replaced with
observeForever
. What is interesting, I looked at this code again and decided to give a try to
awaitClose
function and it seems to work as expected - Channel is not closed immediately. When I’m using
invokeOnClose
, then Channel is closed. Can anyone explain why it acts like that? To conclude, when I changed function body to this one:
Copy code
fun <T> LiveData<T>.asFlow(): Flow<T> = channelFlow {
    value?.let { offer(it) }
    val observer = Observer<T> { t -> t?.let(this::offer) }
    observeForever(observer)
    awaitClose {
        removeObserver(observer)
    }
}
I get expected behavior, so channel is not closed immediately and it’s offering events from LiveData.
d

Dominaezzz

01/09/2020, 1:33 PM
The channel is closed, once the scope exists.
awaitClose
waits for the channel to be closed before returning.
k

KamilH

01/09/2020, 5:49 PM
Thank you for the reply, but I still don’t understand that. Why when I’m calling
invokeOnClose
it’s effectively closes the Channel (and executes lambda) while
awaitClose
not? I thought both of them should just be called when “something” called
close
on the Channel
d

Dominaezzz

01/09/2020, 5:56 PM
invokeOnClose
does what it says and what you expect. It's just that after you call
invokeOnClose
, the code in the
channelFlow
lambda is done and once that happens
channelFlow
closes the channel, which then calls
invokeOnClose
.....
awaitOnClose
happens to also suspend the
channelFlow
lambda until the channel is closed in some other way.
k

KamilH

01/09/2020, 6:24 PM
Thank you 🙂
17 Views