问题
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:
- Make new @Query in DAO and get new LiveData<`List> object in return.
- 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:
- How can I just call onChanged() of my Observer?
- 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