仅通过当前数据使用 MediatorLiveData 的最佳实践 [英] Best practice for using MediatorLiveData only by present data

查看:17
本文介绍了仅通过当前数据使用 MediatorLiveData 的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将 MediatorLiveData 用于多个源的最佳实践是什么?

What is the best practice for using the MediatorLiveData with multiple sources?

我在 ViewModel 中有一个 MediatorLiveData,它是从数据视图中访问的,最终应该呈现出来.

I have a MediatorLiveData in the ViewModel, that is accessed from the view for the data, that should finally be presented.

MediatorLiveData 依赖于多个其他 LiveData.其中一些来自存储库层,其中一些必须在 ViewModel 中处理,然后才能从 MediatorLiveData 访问,还有一些来自 View.

The MediatorLiveData depends on multiple other LiveDatas. Some of them come from the repository layer, some of them have to be processed in the ViewModel before they can be accessed from the MediatorLiveData and some of them come from the View.

所以我当前的实现看起来像以下架构:

So my current implementation looks like the following schema:

public MyViewModel extends ViewModel {
   LiveData<Foo> liveData1;
   LiveData<Bar> liveData2;
   LiveData<FooBar> liveData3;
   //Some other LiveDatas

   MediatorLiveData liveDataForView

   public MyViewModel() {
      liveDataForView = new MediatorLiveData();
      //Do some preprocessing with some of the LiveData
      setupForView();
   }

   public MediatorLiveData getLiveDataForView() {
      return liveDataForView;
   }

   private void setupForView() {
      liveDataForView.addSource(liveData1, (foo -> {
         if(liveData1.getValue() != null && liveData2.getValue() != null && liveData3.getValue() != null /*&& some other LiveData-checks*/)
            liveDataForView.setValue(/*Some combinations of the LiveDatas*/);
      }));
      //Add sources to the MediatorLiveData for any other LiveData
   }
}

通过这个实现,我断言,输出 LiveData 的值是在每个 LiveData 出现之后设置的.在某些情况下,如果我遗漏了一些空检查,我会得到一个 NullPointerException.但是这个解决方案对我来说似乎有点混乱,因为对于我必须添加到 ViewModel 的每个 LiveData,我必须将它添加到每个源.

With this implementation I assert, that the value of the output LiveData is set after every LiveData is present. In some cases, if I left some null-checks out, I got a NullPointerException. But this solution seems a bit messy to me, because for each LiveData I have to add to the ViewModel, I have to add it to every single one of the sources.

推荐答案

首先你需要一些元组:

public class Tuple2<S, T> {
    public final S first;
    public final T second;

    public Tuple2(S first, T second) {
        this.first = first;
        this.second = second;
    }
}

public class Tuple3<S, T, U> {
    public final S first;
    public final T second;
    public final U third;

    public Tuple3(S first, T second, U third) {
        this.first = first;
        this.second = second;
        this.third = third;
    }
}

public class Tuple4<S, T, U, V> {
    public final S first;
    public final T second;
    public final U third;
    public final V fourth;

    public Tuple4(S first, T second, U third, V fourth) {
        this.first = first;
        this.second = second;
        this.third = third;
        this.fourth = fourth;
    }
}

一旦你有了元组,你就可以编写类似于 Transformations.map 的辅助函数,但现在你可以这样做:

Once you have your tuples, you can write helper functions that work akin to Transformations.map except now you could do:

public class LiveDataTransformations {
    private LiveDataTransformations() {}

    public static <S, T> LiveData<Tuple2<S,T>> ifNotNull(LiveData<S> first, LiveData<T> second) {
        MediatorLiveData<Tuple2<S, T>> mediator = new MediatorLiveData<>();

        mediator.addSource(first, (_first) -> {
            T _second = second.getValue();
            if(_first != null && _second != null) {
                mediator.setValue(new Tuple2(_first, _second));
            }
        });

        mediator.addSource(second, (_second) -> {
            S _first = first.getValue();
            if(_first != null && _second != null) {
                mediator.setValue(new Tuple2(_first, _second));
            }
        });

        return mediator;
    }

    public static <S, T, U> LiveData<Tuple3<S,T,U>> ifNotNull(LiveData<S> first, LiveData<T> second, LiveData<U> third) {
        MediatorLiveData<Tuple3<S, T, U>> mediator = new MediatorLiveData<>();

        mediator.addSource(first, (_first) -> {
            T _second = second.getValue();
            U _third = third.getValue();
            if(_first != null && _second != null && _third != null) {
                mediator.setValue(new Tuple3(_first, _second, _third));
            }
        });

        mediator.addSource(second, (_second) -> {
            S _first = first.getValue();
            U _third = third.getValue();
            if(_first != null && _second != null && _third != null) {
                mediator.setValue(new Tuple3(_first, _second, _third));
            }
        });

        mediator.addSource(third, (_third) -> {
            S _first = first.getValue();
            T _second = second.getValue();
            if(_first != null && _second != null && _third != null) {
                mediator.setValue(new Tuple3(_first, _second, _third));
            }
        });

        return mediator;
    }

    public static <S, T, U, V> LiveData<Tuple4<S,T,U, V>> ifNotNull(LiveData<S> first, LiveData<T> second, LiveData<U> third, LiveData<V> fourth) {
        MediatorLiveData<Tuple4<S, T, U, V>> mediator = new MediatorLiveData<>();

        mediator.addSource(first, (_first) -> {
            T _second = second.getValue();
            U _third = third.getValue();
            V _fourth = fourth.getValue();
            if(_first != null && _second != null && _third != null && _fourth != null) {
                mediator.setValue(new Tuple4(_first, _second, _third, _fourth));
            }
        });

        mediator.addSource(second, (_second) -> {
            S _first = first.getValue();
            U _third = third.getValue();
            V _fourth = fourth.getValue();
            if(_first != null && _second != null && _third != null && _fourth != null) {
                mediator.setValue(new Tuple4(_first, _second, _third, _fourth));
            }
        });

        mediator.addSource(third, (_third) -> {
            S _first = first.getValue();
            T _second = second.getValue();
            V _fourth = fourth.getValue();
            if(_first != null && _second != null && _third != null && _fourth != null) {
                mediator.setValue(new Tuple4(_first, _second, _third, _fourth));
            }
        });

        mediator.addSource(fourth, (_fourth) -> {
            S _first = first.getValue();
            T _second = second.getValue();
            U _third = third.getValue();
            if(_first != null && _second != null && _third != null && _fourth != null) {
                mediator.setValue(new Tuple4(_first, _second, _third, _fourth));
            }
        });

        return mediator;
    }
}

现在可以了

LiveData<???> liveDataForView;

private void setupForView() {
   LiveData<Tuple3<Foo, Bar, FooBar>> intermediate =  LiveDataTransformations.ifNotNull(liveData1, liveData2, liveData3);
   liveDataForView = Transformations.map(intermediate, (tuple) -> {
       Foo foo = tuple.first;
       Bar bar = tuple.second;
       FooBar fooBar = tuple.third;

       return /*Some combinations of the LiveDatas*/
   });
}

您可以使用库https://github.com/Zhuinden/livedata-combinetuple-kt 做同样的事情.

You can use the library https://github.com/Zhuinden/livedata-combinetuple-kt to do the same thing.

这篇关于仅通过当前数据使用 MediatorLiveData 的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆