如何正确组合两个实时数据对象

Posted

技术标签:

【中文标题】如何正确组合两个实时数据对象【英文标题】:How to make a combination of two live data objects properly 【发布时间】:2021-02-10 10:22:54 【问题描述】:

我有两个相同类型的 LiveData 对象,我想对输出进行相同的计算。像 Rx 中的合并运算符之类的东西我怎么能做到这一点。目前我正在这样做:

class VM : ViewModel() 
    val input1LiveData = MutableLiveData<Int>()
    val input2LiveData = MutableLiveData<Int>()
    val squareLiveData = MutableLiveData<Int>()


class MyFragment : Fragment() 
    private void fillSquare(input: Int)
        viewmodel.squareLiveData.value = input * input
    
    override onViewCreated()
        viewmodel.input1LiveData.observe(viewLifecycleOwner)
            fillSquare(it * it)
        
        viewmodel.input2LiveData.observe(viewLifecycleOwner)
            fillSquare(it * it)
        
    

我猜这是一个不好的方法

【问题讨论】:

【参考方案1】:

您可以使用MediatorLiveData,它是一种特殊类型的 LiveData,能够连接到其他 liveData 对象作为源。您可以像这样改进上面的代码:

class VM : ViewModel() 
    val input1LiveData = MutableLiveData<Int>()
    val input2LiveData = MutableLiveData<Int>()
    
    val squareLiveData = MediatorLiveData<Int>().apply
        val observer = Observer<T>  value = it*it 
        addSource(input1LiveData, observer)
        addSource(input2LiveData, observer)
    


class MyFragment : Fragment() 
    override onViewCreated()
        viewmodel.squareLiveData.observe(viewLifecycleOwner)
            //do your ui updates
        
    

上面的代码将创建一个有 2 个源的 MediatorLiveData 对象,观察者将计算平方并设置值。


您也可以使用ReactiveLiveData 库,通过反应式方法来实现这一点,使代码更易于编写和阅读:D 就像这样。

class VM : ViewModel() 
    val input1LiveData = MutableLiveData<Int>()
    val input2LiveData = MutableLiveData<Int>()

    val squareLiveData = input1LiveData.merge(input2LiveData).mapit*it


class MyFragment : Fragment() 
    override onViewCreated()
        viewmodel.squareLiveData.observe(viewLifecycleOwner)
            //do your ui updates
        
    

【讨论】:

【参考方案2】:

提供的答案是正确的,确实是可以解决这个问题的MediatorLiveData,例如:

public class CombinedLiveData2<A, B> extends MediatorLiveData<Pair<A, B>> 
    private A a;
    private B b;

    public CombinedLiveData2(LiveData<A> ld1, LiveData<B> ld2) 
        setValue(Pair.create(a, b));

        addSource(ld1, (a) ->  
             if(a != null) 
                this.a = a;
              
             setValue(Pair.create(a, b)); 
        );

        addSource(ld2, (b) ->  
            if(b != null) 
                this.b = b;
             
            setValue(Pair.create(a, b));
        );
    

如果您想为更多 LiveData 执行此操作,可以使用 https://github.com/Zhuinden/livedata-combinetuple-kt/

class VM : ViewModel() 
    val input1LiveData = MutableLiveData<Int>(0)
    val input2LiveData = MutableLiveData<Int>(0)
    val squareLiveData = combineTupleNonNull(input1LiveData, input2LiveData)
                             .map  (input1, input2) -> 
                                 /* do transform */
                             


class MyFragment : Fragment() 
    override onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)    

        viewmodel.squareLiveData.observe(viewLifecycleOwner) 
            // do something with square value
        
    

【讨论】:

以上是关于如何正确组合两个实时数据对象的主要内容,如果未能解决你的问题,请参考以下文章

大数据架构:flume-ng+Kafka+Storm+HDFS 实时系统组合

iOS 内存占用的正确统计数据是啥。实时字节?真实记忆?其他?

大数据如何做验证数据正确性

如何在 PyQtGraph 的一个图中绘制两个实时数据?

如果 Firebase 实时数据库中包含列表,我如何检索对象?

如何一个接一个地合并两个实时数据?