首页 > 解决方案 > 观察者 onChanged 只调用了一次 - LiveData + Flowable (LiveDataStreams)

问题描述

我试图通过使用 a 获取元素,使用库Flowable<List<T>>将其转换为,然后观察最后一个来观察特定表中的数据。观察必须从按钮单击开始。第一次我用户点击按钮时,它从服务器下载数据,将其保存到对应的表中,然后设置观察者。当我再次单击按钮时,问题就出现了,因为它会下载数据并将其保存到表中,但它不会从.LiveDataLiveDataStreamsonChangedObserver

在代码中,您会看到 ParentFragment 的onViewCreated方法showItemsList在那里调用,因为其他子片段必须这样做,但对于当前的情况,我必须在按钮的 onclick 之后开始观察列表。

父片段:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mNavController = Navigation.findNavController(getDataBindingObject().getRoot());

    showItemsList();
}

protected void showItemsList() {
    mViewModel.getList().observe(getViewLifecycleOwner(), listObserver);
}

protected final Observer<List<T>> listObserver = new Observer<List<T>>() {
    @Override
    public void onChanged(List<T> list) {
        getAct().getSupportActionBar().setTitle(getString(mViewModel.getTitleId(), list.size()));
        mViewModel.setListAdapter(list);
    }
};

ChildFragment(当前案例):

@Override
protected void showItemsList() {
    mDataBinding.searchButton.setOnClickListener(v -> {
        mViewModel.download()
                .subscribe(downloaded -> super.showItemsList()
                        , t -> DialogUtils.showMessage(R.string.error_binding_data));
    });
}

视图模型:

public LiveData<List<T>> getList() {
    if (list == null) {
        LiveData<List<T>> lD = LiveDataReactiveStreams.fromPublisher(mRepository.getList());
        list = new MediatorLiveData<>();
        list.addSource(lD, l -> {
            list.setValue(l);
            list.remove(lD);
        });
    }
    return list;
}

存储库:

public Flowable<List<T>> getList() {
    if (list == null) list = dao.getItems();
    return list;
}

道:

public abstract Flowable<List<MyItem>> getItems();

标签: androidrx-javaandroid-livedataflowable

解决方案


您在负责从 转换为 的代码中犯了一个Flowable错误LiveData

在第一次调用 时getList(),您创建了一个LiveData观察 的对象Flowable,但在检索到第一个项目后,您停止观察Flowable。稍后您将其分配LiveData给一个字段。

在第二次调用 时getList(),您将LiveData对象分配给该字段(没有来源),因此您的片段中的观察者不会收到通知。

您可以像这样修改您的代码

public LiveData<List<T>> getList() {
    if (list == null) {
        LiveData<List<T>> lD = LiveDataReactiveStreams.fromPublisher(mRepository.getList());
        list = new MediatorLiveData<>();
        list.addSource(lD, l -> {
            list.setValue(l);
        });
    }
    return list;
}

推荐阅读