Hello. I’m trying to combine multiple objects into...
# android
l
Hello. I’m trying to combine multiple objects into one
Copy code
fun <A, B>LiveData<A>.combine(
    vararg other: LiveData<*>,
    combiner: (/*Don't know*/) -> B
) {
    val result = MediatorLiveData<B>()
    other.forEach { liveData ->
        result.addSource(liveData) { 
            if (other.toList().all { it.value != null }) {
                result.postValue(combiner(other))
            }
        }
    }
}
usage :
Copy code
fun a() {
    MutableLiveData<Int>().combine2(MutableLiveData<Boolean>()) { entry1, entry2, etc ->
        
    }
}
Do you have any ideas ?
s
Probably not the advice you want, but I'd really avoid using LiveData like that. Kotlin flows are significantly easier to work with for performing operations like that. If you need a live data at the end then you can do that (though I don't bother and keep everything in flows). https://developer.android.com/kotlin/flow
l
Yes, Flow is great. But I can’t migrate everything now. Thanks anyway
And, from what I know,
Flow.combine
allow a two flows to be merged together. And what I’m looking for is exactly the same but with an indeterminate numbers of flow/Livedata
f
you can always convert your
LiveData
to a
flow
with
asFlow
and then use the
combine
operator
e
you can destructure in the lambda, for example
Copy code
private object Sentinel
fun <T> merge(vararg sources: LiveData<T>): LiveData<List<T>> {
    val data = Array<Any?>(sources.size) { Sentinel }
    val merged = MediatorLiveData<List<T>>()
    sources.forEachIndexed { i, source ->
        merged.addSource(source) { value ->
            data[i] = value
            if (data.all { it !== Sentinel }) {
                merged.value = data.map { @Suppress("UNCHECKED_CAST") it as T }
            }
        }
    }
    return merged
}

merge(as, bs, cs).observe(lifecycle) { (a, b, c) -> ... }
or move the transform into the function using the same single-argument approach, but if you want to guarantee that
as, bs, cs
match up with
a, b, c
, you'd need separate overloads for each parameter list length
l
@Francesc Yes but combine work with 2 flows, and I need more than 4 @ephemient That’s way better ! I’ll try it. Thanks
f
combine works with more than 2 flows
the standard lib provides overloads for up to 5 flows, but you could easily create your own that takes more if you need to.
d
do you have some snippets for that?