Android Livedata -SwitchMap在第二个更新中未触发



我有一个 LiveData对象,该对象取决于另一个 LiveData。据我了解,Transformations.switchMap应该允许它们链接。但是switchMap处理程序仅触发一次,并且不会在进一步更新中做出反应。相反,如果我在第一个对象上使用observe,并且在准备好时,请检索第二个对象,它可以正常工作,但是在这种情况下,我必须在Activity而不是ViewModel中进行操作。是否可以将LiveData对象(例如Transformations.switchMap)进行链接,但不仅接收所有更新,不仅是第一个更新?

这是使用switchMap的尝试:

LiveData<Resource<User>> userLiveData = usersRepository.get();
return Transformations.switchMap(userLiveData, resource -> {
    if (resource.status == Status.SUCCESS && resource.data != null) {
        return apiService.cartItems("Bearer " + resource.data.token);
    } else {
        return AbsentLiveData.create();
    }
});

这是一种在活动中使用observe的方法(有效但需要保持逻辑活动):

viewModel.user().observe(this, x -> {
    if (x != null && x.data != null) {
        viewModel.items(x.data.token).observe(this, result -> {
            // use result
        });
    }
});

我试图做与您类似的事情。我有一个livedata something,当这种变化时,我想根据属性从DB查询somethingElse。因为该属性可以为null,所以如果我用它查询DB,我将得到一个例外。因此,如果属性为null,我将返回一个空的mutableLiveData。

我注意到,当我返回这个空的MutableLivedata时,订阅somethingElse的观察者没有得到任何更新。我在您的答案上看到了您最终使用了一个介导的人。然后,我使用调试器逐步浏览了代码,并注意到SwitchMap还使用了中介词。

进行了一些实验后,我意识到,创建空的mutableLiveData时,它的初始值是无效的,不会触发任何更新。如果我明确设置该值,则将通知观察者。

somethingElse = Transformations.switchMap(something, somethingObject -> {
                if (something.someProperty() != null) {
                    return repository.getSomethingElseByProperty(something.someProperty());
                }else{
                    MutableLiveData<SomethingElse> empty = new MutableLiveData<>();
                    empty.setValue(null);//need to set a value, to force update of observers
                    return empty;
                }

这里的代码对我有用。在问题中,您使用了一个缺失的情况,我不知道它是如何实现的,因此我不确定在这种情况下它是否完全有效。

作为解决方法,我使用了MediatorLiveData。我将第一个调用的结果添加为源,当准备就绪时,将其替换为最终呼叫:

MediatorLiveData<MyResponse> result = new MediatorLiveData<>();
LiveData<Resource<User>> source = this.get();
result.addSource(source, resource -> {
    if (resource.status == Status.SUCCESS && resource.data != null) {
        result.removeSource(source);
        result.addSource(apiService.cartItems("Bearer " + resource.data.token), result::postValue);
    }
});
return result;

最新更新