Merge "Have FlowLiveData.asFlow use callbackFlow" into androidx-main
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
index 7c2d8ed..fd50175 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
@@ -27,10 +27,11 @@
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -102,24 +103,20 @@
* LiveData due to a slow collector, so collector always gets the most recent value emitted.
*/
@OptIn(DelicateCoroutinesApi::class)
-public fun <T> LiveData<T>.asFlow(): Flow<T> = flow {
- val channel = Channel<T>(Channel.CONFLATED)
+public fun <T> LiveData<T>.asFlow(): Flow<T> = callbackFlow {
val observer = Observer<T> {
- channel.trySend(it)
+ trySend(it)
}
withContext(Dispatchers.Main.immediate) {
observeForever(observer)
}
- try {
- for (value in channel) {
- emit(value)
- }
- } finally {
+
+ awaitClose {
GlobalScope.launch(Dispatchers.Main.immediate) {
removeObserver(observer)
}
}
-}
+}.conflate()
/**
* Creates a LiveData that has values collected from the origin [Flow].
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt b/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
index 97cdd15..ab075f6 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
@@ -86,11 +86,14 @@
fun reusingFlow() {
val ld = MutableLiveData<Int>()
val flow = ld.asFlow()
- mainScope.launch { ld.value = 1 }
val firstCollection = testScope.launch {
assertThat(flow.first()).isEqualTo(1)
}
scopes.triggerAllActions()
+ assertThat(ld.hasActiveObservers()).isTrue()
+
+ mainScope.launch { ld.value = 1 }
+ scopes.triggerAllActions()
// check that we're done with previous collection
assertThat(ld.hasActiveObservers()).isFalse()
assertThat(firstCollection.isCompleted).isTrue()
@@ -119,7 +122,7 @@
assertThat(flowB.take(2).toList()).isEqualTo(listOf(1, 2))
}
scopes.triggerAllActions()
- assertThat(ld.hasActiveObservers())
+ assertThat(ld.hasActiveObservers()).isTrue()
mainScope.launch { ld.value = 1 }
scopes.triggerAllActions()