Updating a RecyclerView by a new LiveData<List> return from Room dynamically

試著忘記壹切 提交于 2021-01-07 06:11:57

问题


I have a conventional Room->DAO->Livedata->Repositiry->ViewModel->RecyclerView app. Different buttons of UI must pass different lists of data to RecyclerView.
By button click I want:

  1. Make new @Query in DAO and get new LiveData<`List> object in return.
  2. Put this new data into the RecyclerViewAdapter and call notifyDataSetChanged () to make new List visuals.

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

The recyclerView is updated via onChanged of Observer like this:

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();

The problem is that my Observer does not call the onChange method when LiveData receives new value from DAO. I believe it is because this LiveData’s content is not CHANGED but REPLACED by another LiveData.

I tried to re-subscribe the Observer to LiveData again and it somewhat worked, but when I try to call some conventional Room queries like @Delete, I got multiple (up to 10!) onChange calls and some of them behave weirdly and pass the wrong List to RVadapter.

So there two questions:

  1. How can I just call onChanged() of my Observer?
  2. Is there some other stylish way of passing new LiveData object to RecyclerView dynamically?

回答1:


1)

In viewModel , create a getter method for live data:

//...

private LiveData<List<Entry>> liveData;

//...

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

in 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 is very helpful to update your list in recycler view and it gives you some nice animations.




回答2:


I tried to re-subscribe the Observer to LiveData again and it somewhat worked, but when I try to call some conventional Room queries like @Delete, I got multiple (up to 10!) onChange calls and some of them behave weirdly and pass the wrong List to RVadapter.

This would make sense if you didn't first unsubscribe your observer from the old LiveData object... the one you replace when your query changes.

If your query updates, you will need to get a new LiveData from the DAO. If you overwrite your old LiveData with the new one, you will not only need to (re-)subscribe your Observer to the new one, you will also need to unsubscribe it from the old one. Otherwise it will live on and keep updating the observer.



来源:https://stackoverflow.com/questions/58730425/updating-a-recyclerview-by-a-new-livedatalist-return-from-room-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!