本文介绍了具有多个参数的MediatorLiveData或switchMap转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ViewModel中使用 Transformations.switchMap 在片段中观察到的我的LiveData集合对code参数的更改有反应.

I am using Transformations.switchMap in my ViewModel so my LiveData collection, observed in my fragment, reacts on changes of code parameter.

这很完美:

public class MyViewModel extends AndroidViewModel {

    private final LiveData<DayPrices> dayPrices;
    private final MutableLiveData<String> code = new MutableLiveData<>();
    // private final MutableLiveData<Integer> nbDays = new MutableLiveData<>();
    private final DBManager dbManager;

    public MyViewModel(Application application) {
        super(application);
        dbManager = new DBManager(application.getApplicationContext());
        dayPrices = Transformations.switchMap(
            code,
            value -> dbManager.getDayPriceData(value/*, nbDays*/)
        );
    }

    public LiveData<DayPrices> getDayPrices() {
        return dayPrices;
    }

    public void setCode(String code) {
        this.code.setValue(code);
    }

    /*public void setNbDays(int nbDays) {
        this.nbDays.setValue(nbDays);
    }*/

}

public class MyFragment extends Fragment {

    private MyViewModel myViewModel;

    myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    myViewModel.setCode("SO");
    //myViewModel.setNbDays(30);
    myViewModel.getDayPrices().observe(MyFragment.this, dataList -> {
        // update UI with data from dataList
    });
}

问题

我现在需要另一个参数(在上面的代码中用nbDays注释),以便我的LiveData对象对两个参数更改(codenbDays)都做出反应.

I now need another parameter (nbDays commented in the code above), so that my LiveData object reacts on both parameters change (code and nbDays).

如何链接转换?

一些阅读将我指向 MediatorLiveData ,但确实如此不能解决我的问题(仍然需要使用2个参数调用单个DB函数,我不需要合并2个liveDatas).

Some reading pointed me to MediatorLiveData, but it does not solve my problem (still need to call single DB function with 2 parameters, I don't need to merge 2 liveDatas).

因此,我尝试使用此方法而不是switchMap,但codenbDays始终为空.

So I tried this instead of switchMap but code and nbDays are always null.

dayPrices.addSource(
    dbManager.getDayPriceData(code.getValue(), nbDays.getValue),
    apiResponse -> dayPrices.setValue(apiResponse)
);

一种解决方案是将对象作为单个参数传递,因为我很确定对此有一个简单的解决方案.

One solution would be to pass an object as single parameter by I'm pretty sure there is a simple solution to this.

推荐答案

来源: https://plus.google.com/+MichielPijnackerHordijk/posts/QGXF9gRomVi

要具有多个switchMap()触发器,您需要使用自定义MediatorLiveData来观察LiveData对象的组合-

To have multiple triggers for switchMap(), you need to use a custom MediatorLiveData to observe the combination of the LiveData objects -

class CustomLiveData extends MediatorLiveData<Pair<String, Integer>> {
    public CustomLiveData(LiveData<String> code, LiveData<Integer> nbDays) {
        addSource(code, new Observer<String>() {
            public void onChanged(@Nullable String first) {
                setValue(Pair.create(first, nbDays.getValue()));
            }
        });
        addSource(nbDays, new Observer<Integer>() {
            public void onChanged(@Nullable Integer second) {
                setValue(Pair.create(code.getValue(), second));
            }
        });
    }
}

然后您可以执行此操作-

Then you can do this -

CustomLiveData trigger = new CustomLiveData(code, nbDays);
LiveData<DayPrices> dayPrices = Transformations.switchMap(trigger, 
    value -> dbManager.getDayPriceData(value.first, value.second));

如果您使用Kotlin并想使用泛型:

If you use Kotlin and want to work with generics:

class DoubleTrigger<A, B>(a: LiveData<A>, b: LiveData<B>) : MediatorLiveData<Pair<A?, B?>>() {
    init {
        addSource(a) { value = it to b.value }
        addSource(b) { value = a.value to it }
    }
}

然后:

val dayPrices = Transformations.switchMap(DoubleTrigger(code, nbDays)) {
    dbManager.getDayPriceData(it.first, it.second)
}

这篇关于具有多个参数的MediatorLiveData或switchMap转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 07:23