通过Room动态返回的新LiveData <List>更新RecyclerView

时间:2019-11-06 12:41:19

标签: android android-recyclerview android-room android-livedata

我有一个常规的Room-> DAO-> Livedata-> Repositiry-> ViewModel-> RecyclerView应用程序。 UI的不同按钮必须将不同的数据列表传递给RecyclerView。
通过按钮单击我想要的:

  1. 在DAO中进行新的@Query并获取新的LiveData <`List>对象作为回报。
  2. 将此新数据放入RecyclerViewAdapter中,并调用notifyDataSetChanged()以创建新的List外观。

The Dao @Query:

@Query("SELECT * FROM entry_table WHERE path LIKE :path ORDER BY priority DESC")
LiveData<List<Entry>> getNotesOfFolder(String path);    //Returns LiveData with List of Entries

通过Observer的onChanged更新recyclerView,如下所示:

public class RecyclerViewActivity extends AppCompatActivity {…
Observer<List<Entry>> entryObserver = new Observer<List<Entry>>() {
    @Override
    public void onChanged(List<Entry> entries) {
        recyclerAdapter.setEntries(entries);
    }
};
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.EntryHolder> {…
public void setEntries(List<Entry> entries) {
    this.entries = entries; //setting LiveData content to adapter's List (i.e. entries)
    notifyDataSetChanged();

问题是LiveData从DAO接收新值时,我的观察者未调用onChange方法。我相信是因为此LiveData的内容不是被其他LiveData更改而是替换。

我试图再次为Observer重新订阅LiveData,但它有些起作用,但是当我尝试调用一些常规的Room查询(例如@Delete)时,我遇到了多个(最多10个!)onChange调用,其中一些行为很奇怪并将错误的列表传递给RVadapter。

所以有两个问题:

  1. 如何仅调用观察者的onChanged()?
  2. 是否存在将时尚的LiveData对象动态传递到RecyclerView的其他时尚方法?

2 个答案:

答案 0 :(得分:1)

1)

viewModel中,为实时数据创建一个getter方法:

//...

private LiveData<List<Entry>> liveData;

//...

public LiveData<List<Entry>> getLiveData() {
    return liveData;
}

Activity中:

  @Override
  protected void onCreate(Bundle savedInstanceState) {

      //...

      viewModel.getLiveData().observe(this, new Observer<List<Entry>>() {
          @Override
          public void onChanged(List<Entry> entryList) {
              //set new value here
          }
      });

  }

2)DiffUtil对在回收站视图中更新列表非常有帮助,并且为您提供了一些精美的动画。

答案 1 :(得分:0)

我试图再次为Observer重新订阅LiveData,但它有些起作用,但是当我尝试调用一些常规的Room查询(如@Delete)时,我遇到了多个(最多10个!)onChange调用,其中一些行为异常并将错误的列表传递给RVadapter。

如果您没有先从 old LiveData对象中退订您的观察者...这将是有道理的...在查询更改时替换您的观察者。

如果查询更新,则需要从DAO获取新的LiveData。如果用新的旧LiveData覆盖旧的LiveData,则不仅需要将观察者(重新)订阅到新的LiveData,还需要从旧的Observer取消订阅。否则它将继续存在并不断更新观察者。