问题
I have a Main Activity that extends AppCompatActivity with a RecyclerView. It is working fine to load a List of CardViews from a Room database and then filter the List. Problem occurs after pressing Back space to return the user to the original List.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
...
mViewModel = ViewModelProviders.of(MainActivity.this).get(MainViewModel.class);
mViewModel.getAllCards().observe(this, new Observer<List<Card>>() {
@Override
public void onChanged(@Nullable final List<Card> cards) {
if (cards == null) {
return;
}
adapter.setCardList(cards);
}
});
}
I filter the List using a click on TextView and that is working fine as well.
allWaitingfors.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mViewModel.filterListCardTypeWaitingfor() != null) {
mViewModel.filterListCardTypeWaitingfor().removeObservers((AppCompatActivity) context);
}
mViewModel.filterListCardTypeWaitingfor().observe(MainActivity.this, new Observer<List<Card>>() {
@Override
public void onChanged(@Nullable final List<Card> filterWaitingforCards) {
if (filterWaitingforCards != null && filterWaitingforCards.size() == 0) {
Toast.makeText(MainActivity.this, "There are no cards", Toast.LENGTH_SHORT).show();
}
else {
adapter.setCardList(filterWaitingforCards);
}
}
});
dialogFilter.dismiss();
}
});
If the List is currently filtered and then the user presses Back space, I'd like to return the user to the original RecyclerView list. This is where my problem is. The CardViews are not loading in the List. What am I missing here?
@Override
public void onBackPressed() {
if (mViewModel.filterListCardTypeWaitingfor() != null) {
mViewModel.filterListCardTypeWaitingfor().removeObservers((AppCompatActivity) context);
mViewModel.getAllCards().removeObservers((AppCompatActivity) context);
mViewModel.getAllCards().observe(this, new Observer<List<Card>>() {
@Override
public void onChanged(@Nullable final List<Quickcard> cards2) {
if (cards2 == null) {
return;
}
else {
adapter.setCardList(cards2);
}
});
}
else {
Toast.makeText(MainActivity.this, "Exit", Toast.LENGTH_SHORT).show();
MainActivity.this.finish();
super.onBackPressed();
}
}
Adapter
public class CardListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private LayoutInflater layoutInflater;
private List<Card> cardList = Collections.emptyList();
public CardListAdapter(Context context, RecyclerItemClickListener recyclerItemClickListener) {
this.context = context;
this.layoutInflater = LayoutInflater.from(context);
}
…
public void setCardList(List<Card> newCardsList) {
if (cardList != null) {
PostDiffCallback postDiffCallback = new PostDiffCallback(cardList, newCardsList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(postDiffCallback);
cardList.clear();
this.cardList = newCardsList;
diffResult.dispatchUpdatesTo(this);
} else {
this.cardList = newCardsList;
}
}
class PostDiffCallback extends DiffUtil.Callback {
private final List<Card> oldPosts, newPosts;
private PostDiffCallback(List<Card> oldPosts, List<Card> newPosts) {
this.oldPosts = oldPosts;
this.newPosts = newPosts;
}
@Override
public int getOldListSize() {
return oldPosts.size();
}
@Override
public int getNewListSize() {
return newPosts.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldPosts.get(oldItemPosition).getId() == newPosts.get(newItemPosition).getId();
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldPosts.get(oldItemPosition).equals(newPosts.get(newItemPosition));
}
}
回答1:
When you received the data from the ViewModel live data observe, in onChanged method
Method Inside fragment or inside Activity where you can get the live data observation and send to adapter newData method.
controlRoomViewModel.getLiveDispatchData().observe(this, new Observer<Dispatch>(){
@Override
public void onChanged(@Nullable Dispatch dispatch) {
if (dispatch != null) {
content = dispatch.getContent();
adapter.addContentItems((ArrayList<ContentItem>) content);
}
}
});
Method of the adapter
public void addContentItems(ArrayList<ContentItem> newContentItems) {
if (newContentItems == null) {
return;
}
if (contentItems != null && contentItems.size() > 0)
contentItems.clear();
for (ContentItem contentItem : newContentItems) {
contentItems.add(contentItem);
}
notifyDataSetChanged();
}
Mainly you have to call notifyDataSetChanged(); to re-render the views because data gots changed.
来源:https://stackoverflow.com/questions/56766367/recyclerview-how-to-refresh-full-list-of-cardviews-with-viewmodel