-
呼唤远方
你需要的是所谓的zip功能:fun <A, B> zip(first: LiveData<A>, second: LiveData<B>): LiveData<Pair<A, B>> { val mediatorLiveData = MediatorLiveData<Pair<A, B>>() var isFirstEmitted = false var isSecondEmitted = false var firstValue: A? = null var secondValue: B? = null mediatorLiveData.addSource(first) { isFirstEmitted = true firstValue = it if (isSecondEmitted) { mediatorLiveData.value = Pair(firstValue!!, secondValue!!) isFirstEmitted = false isSecondEmitted = false } } mediatorLiveData.addSource(second) { isSecondEmitted = true secondValue = it if (isFirstEmitted) { mediatorLiveData.value = Pair(firstValue!!, secondValue!!) isFirstEmitted = false isSecondEmitted = false } } return mediatorLiveData}现在,您可以调用zip(firstLiveData,secondLiveData)并观察它。
-
守着星空守着你
这是一个更通用的版本,它允许您观察多个LiveData.fun zipLiveData(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any>> { //MediatorLiveData used to merge multiple LiveDatas return MediatorLiveData<ArrayList<Any>>().apply { val zippedObjects = ArrayList<Any>() liveItems.forEach { //Add each LiveData as a source for the MediatorLiveData addSource(it) { item -> //Add value to list item?.let { it1 -> zippedObjects.add(it1) } if (zippedObjects.size == liveItems.size) { //If all the LiveData items has returned a value, save that value in MediatorLiveData. value = zippedObjects //Clear the list for next time zippedObjects.clear() } } } }}上面的函数不会将null值添加到列表中,假设您null也想添加值,您需要按照以下几行做一些事情,fun zipLiveData(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any?>> { return MediatorLiveData<ArrayList<Any?>>().apply { val zippedObjects = ArrayList<Any?>() liveItems.forEach { addSource(it) { item -> zippedObjects.add(item) if (zippedObjects.size == liveItems.size) { value = zippedObjects zippedObjects.clear() } } } }}更新- 我刚刚意识到上述方法不保留项目的“顺序” LiveData(例如,如果第二个LiveData在第一个之前发布了一个值,您将获得值[secondLiveDataValue, firstLiveDataValue]而不是预期值[firstLiveDataValue, secondLiveDataValue])。如果您希望保留项目值的“顺序”,则可以改用以下两个函数之一LiveData。//If you know the LiveDatas won't get null valuesfun zipLiveData(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any?>> { return MediatorLiveData<ArrayList<Any?>>().apply { var zippedObjects = arrayOfNulls<Any>(liveItems.size) liveItems.forEachIndexed { index, liveData -> addSource(liveData) { item -> zippedObjects[index] = item if (!zippedObjects.contains(null)) { value = zippedObjects.toCollection(ArrayList()) zippedObjects = arrayOfNulls(liveItems.size) } } } }}//Incase your LiveDatas might have null valuesfun zipLiveDataWithNull(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any?>> { return MediatorLiveData<ArrayList<Any?>>().apply { val zippedObjects = arrayOfNulls<Any>(liveItems.size) val zippedObjectsFlag = BooleanArray(liveItems.size) liveItems.forEachIndexed { index, liveData -> addSource(liveData) { item -> zippedObjects[index] = item zippedObjectsFlag[index] = true if (!zippedObjectsFlag.contains(false)) { value = zippedObjects.toCollection(ArrayList()) for(i in 0 until liveItems.size) { zippedObjectsFlag[i] = false } } } } }}
-
牧羊人nacy
这个扩展功能对我有用fun <A, B> LiveData<A>.zipWith(stream: LiveData<B>): LiveData<Pair<A, B>> { val result = MediatorLiveData<Pair<A, B>>() result.addSource(this) { a -> if (a != null && stream.value != null) { result.value = Pair(a, stream.value!!) } } result.addSource(stream) { b -> if (b != null && this.value != null) { result.value = Pair(this.value!!, b) } } return result}
-
蛊毒传说
我的解决方案有点受到 rxjava zip 运算符的启发,inline fun <reified I1, I2, O> biZip(inputLiveData1: LiveData<I1>, inputLiveData2: LiveData<I2>, crossinline tranform: (data1: I1, data2: I2) -> O): LiveData<O> { var input1: I1? = null var input2: I2? = null val mediatorLiveData = MediatorLiveData<O>() mediatorLiveData.addSource(inputLiveData1) { input1 = it if (input1 != null && input2 != null) { mediatorLiveData.value = tranform.invoke(input1!!, input2!!) } } mediatorLiveData.addSource(inputLiveData2) { input2 = it if (input1 != null && input2 != null) { mediatorLiveData.value = tranform.invoke(input1!!, input2!!) } } return mediatorLiveData}现在你可以像这样使用它val liveDataString = MutableLiveData<String>()val liveDataInt = MutableLiveData<Int>()val liveDataofTest = biZip<String, Int, Test>(liveDataString, liveDataInt) { data1:String, data2:Int -> return@biZip Test(data1, data2)}测试 pojo 就像data class Test(val name:String,value:Int)
-
沧海一幻觉
您可以像扩展功能一样直接使用它fun <A, B, C> LiveData<A>.zip(stream: LiveData<B>, func: (source1: A?, source2: B?) -> C): LiveData<C> { val result = MediatorLiveData<C>() result.addSource(this) { a -> result.setValue(func.invoke(a,stream.value)) } result.addSource(stream) { b -> result.setValue(func.invoke(this.value, b)) } return result}