I have a list of `Flow`s of nullables and I would ...
# coroutines
e
I have a list of `Flow`s of nullables and I would like to combine them in a way, that I only observe the second Flow, when the first one emits a
null
. I thought of something like that (for 2 `Flow`s):
Copy code
fun <T : Any> takeFirstNotNull(flow1: Flow<T?>, flow2: Flow<T?>): Flow<T?> {
    return flow1.transform {
            if (it != null) emit(it) else emitAll(flow2)
    },
}
Is there a simpler solution for this (especially, if this might be done for more `Flow`s)?
j
so you want to collect the first flow while it is not null, and then stop that and start emitting the second one?
Copy code
fun <T : Any> takeFirstNotNull(flow1: Flow<T?>, flow2: Flow<T?>): Flow<T?> {
   return flow1.takeWhile { it != null }.onCompletion { exception ->
      if (exception  == null) {
         emitAll(flow2)
      }
   }
}
and with the help of a helper extension function:
Copy code
fun <T : Any> takeFirstNotNull(flow1: Flow<T?>, flow2: Flow<T?>): Flow<T?> {
	return flow1.takeWhile { it != null }.concatOnCompletion(flow2)
}

fun <T> Flow<T>.concatOnCompletion(other: Flow<T>) = onCompletion { exception ->
	if (exception == null) {
		emitAll(other)
	}
}
it looks cleaner
e
No, I don't want to stop emitting the first one. I want a Flow as result, which emits as less `null`s as possible, coming from different sources with a specific priority of the sources. So: take as long values from source 1, as long as the values aren't null. If we get a
null
value, get the values from source 2, as long as the value in source 1 stays
null
. Maybe as background info, my sources are `StateFlow`s, if this would make a difference.
j
Something like this then?
Copy code
fun <T : Any> takeFirstNotNull(flow1: Flow<T?>, flow2: Flow<T?>): Flow<T?> {
	return combine(flow1, flow2) { value1, value2 -> value1 ?: value2 }
}
this will return the latest flow2 if flow1 gets null
but it will resume flow1 when it gets non-null
e
Yes, but it would always subscribe to flow2. I thought, it would be better, if the subscription to flow2 only starts, when it's really needed, so when flow1 has a null value.
j
then I guess your original should work if you use
transformLatest
👍 1
because otherwise you will collect the second flow until it is completed (which you don't want I guess)
👍 1