Essayer de comprendre quel est le problème avec la mise à jour RecyclerView
de l'adaptateur.
Après avoir reçu une nouvelle liste de produits, j'ai essayé de:
Mettez à jour le à
ArrayList
partir du fragment oùrecyclerView
est créé, définissez de nouvelles données sur l'adaptateur, puis appelezadapter.notifyDataSetChanged()
; cela n'a pas fonctionné.Créez un nouvel adaptateur, comme d'autres l'ont fait, et cela a fonctionné pour eux, mais aucun changement pour moi:
recyclerView.setAdapter(new RecyclerViewAdapter(newArrayList))
Créez une méthode dans
Adapter
laquelle met à jour les données comme suit:public void updateData(ArrayList<ViewModel> viewModels) { items.clear(); items.addAll(viewModels); notifyDataSetChanged(); }
Ensuite, j'appelle cette méthode chaque fois que je veux mettre à jour la liste des données; cela n'a pas fonctionné.
Pour vérifier si je peux modifier le recyclerView de quelque manière que ce soit, et j'ai essayé de supprimer au moins un élément:
public void removeItem(int position) { items.remove(position); notifyItemRemoved(position); }
Tout est resté tel quel.
Voici mon adaptateur:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements View.OnClickListener {
private ArrayList<ViewModel> items;
private OnItemClickListener onItemClickListener;
public RecyclerViewAdapter(ArrayList<ViewModel> items) {
this.items = items;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
v.setOnClickListener(this);
return new ViewHolder(v);
}
public void updateData(ArrayList<ViewModel> viewModels) {
items.clear();
items.addAll(viewModels);
notifyDataSetChanged();
}
public void addItem(int position, ViewModel viewModel) {
items.add(position, viewModel);
notifyItemInserted(position);
}
public void removeItem(int position) {
items.remove(position);
notifyItemRemoved(position);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ViewModel item = items.get(position);
holder.title.setText(item.getTitle());
Picasso.with(holder.image.getContext()).load(item.getImage()).into(holder.image);
holder.price.setText(item.getPrice());
holder.credit.setText(item.getCredit());
holder.description.setText(item.getDescription());
holder.itemView.setTag(item);
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public void onClick(final View v) {
// Give some time to the ripple to finish the effect
if (onItemClickListener != null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
onItemClickListener.onItemClick(v, (ViewModel) v.getTag());
}
}, 0);
}
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView image;
public TextView price, credit, title, description;
public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
price = (TextView) itemView.findViewById(R.id.price);
credit = (TextView) itemView.findViewById(R.id.credit);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
}
}
public interface OnItemClickListener {
void onItemClick(View view, ViewModel viewModel);
}
}
Et j'initie RecyclerView
comme suit:
recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 5));
adapter = new RecyclerViewAdapter(items);
adapter.setOnItemClickListener(this);
recyclerView.setAdapter(adapter);
Alors, comment puis-je réellement mettre à jour les données de l'adaptateur afin d'afficher les éléments nouvellement reçus?
Mise à jour: le problème était que la disposition dans laquelle gridView était présentée était la suivante:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:tag="catalog_fragment"
android:layout_height="match_parent">
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"/>
<ImageButton
android:id="@+id/fab"
android:layout_gravity="top|end"
style="@style/FabStyle"/>
</FrameLayout>
</LinearLayout>
Ensuite, je viens de supprimer LinearLayout
et FrameLayout
de créer la disposition parent.
la source
items.clear(); items.addAll(newItems);
est un motif laid. Si vous avez vraiment besoin d'une copie défensive ici, ceitems = new ArrayList(newItems);
serait moins moche.Réponses:
Je travaille avec RecyclerView et la suppression et la mise à jour fonctionnent bien.
1) SUPPRIMER: Il y a 4 étapes pour supprimer un élément d'un RecyclerView
Cette ligne de codes fonctionne pour moi.
2) METTRE À JOUR LES DONNÉES: La seule chose que je devais faire est
Vous avez dû faire tout cela dans le code Actvity / Fragment et non dans le code de l'adaptateur RecyclerView.
la source
recycler.removeViewAt(position);
(ou plutôtrecycler.removeAllViews()
) étaient cruciales.Ceci est une réponse générale pour les futurs visiteurs. Les différentes façons de mettre à jour les données de l'adaptateur sont expliquées. Le processus comprend à chaque fois deux étapes principales:
Insérer un seul élément
Ajoutez "Pig" à l'index
2
.Insérer plusieurs éléments
Insérez trois autres animaux à l'index
2
.Supprimer un seul élément
Supprimer "Pig" de la liste.
Supprimer plusieurs éléments
Supprimer "Chameau" et "Mouton" de la liste.
Supprimer tous les éléments
Effacez toute la liste.
Remplacer l'ancienne liste par une nouvelle liste
Effacez l'ancienne liste puis ajoutez-en une nouvelle.
Le
adapter
a une référence àdata
, il est donc important que je n'aie pas définidata
de nouvel objet. Au lieu de cela, j'ai effacé les anciens élémentsdata
, puis ajouté les nouveaux.Mettre à jour un seul élément
Modifiez l'élément "Mouton" pour qu'il indique "J'aime les moutons".
Déplacer un seul élément
Déplacez le "mouton" d'une position
3
à l'autre1
.Code
Voici le code du projet pour votre référence. Le code de l'adaptateur RecyclerView se trouve à cette réponse .
MainActivity.java
Remarques
notifyDataSetChanged()
, aucune animation ne sera effectuée. Cela peut également être une opération coûteuse, il n'est donc pas recommandé de l'utilisernotifyDataSetChanged()
si vous ne mettez à jour qu'un seul élément ou une plage d'éléments.Une étude plus approfondie
la source
Update single item
, aurait dû être j'aime les tortuesC'est ce qui a fonctionné pour moi:
Après avoir créé un nouvel adaptateur qui contient la liste mise à jour (dans mon cas, c'était une base de données convertie en ArrayList) et l'avoir définie comme adaptateur, j'ai essayé
recyclerView.invalidate()
et cela a fonctionné.la source
YourAdapter adapter = (YourAdapter) recyclerView.getAdapter(); adapter.yourSetterMethod(newList); adapter.notifyDataSetChanged();
Cela étant dit, cela ressemble à ce que le PO a essayé en premier (en ajoutant simplement cela en tant que commentaire afin qu'il puisse aider quelqu'un d'autre, comme cela a fonctionné dans mon cas).vous avez 2 options pour ce faire: actualiser l'interface utilisateur à partir de l'adaptateur:
ou actualisez-le à partir de recyclerView lui-même:
la source
Une autre option consiste à utiliser diffutil . Il comparera la liste d'origine à la nouvelle liste et utilisera la nouvelle liste comme mise à jour en cas de changement.
Fondamentalement, nous pouvons utiliser DiffUtil pour comparer les anciennes données aux nouvelles données et le laisser appeler notifierItemRangeRemoved, notifierItemRangeChanged et notifierItemRangeInsert en votre nom.
Un exemple rapide d'utilisation de diffUtil au lieu de notifyDataSetChanged:
Je fais le calcul de Diff sur le thread principal au cas où ce serait une grande liste.
la source
getItems()
. Comment savez-vous quelles données de la liste d'origine doivent être supprimées / ajoutées / mises à jour?Mettre à jour les données de listview, gridview et recyclerview
ou
la source
Le meilleur et le plus cool moyen d'ajouter de nouvelles données aux données actuelles est
la source
J'ai résolu le même problème d'une manière différente. Je n'ai pas de données que j'attends du fil d'arrière-plan, alors commencez par une liste emty.
C'est tout.
la source
Ces méthodes sont efficaces et bonnes pour commencer à utiliser une base
RecyclerView
.Vous pouvez les implémenter à l'intérieur d'une classe d'adaptateur ou dans votre fragment ou activité, mais dans ce cas, vous devez instancier l'adaptateur pour appeler les méthodes de notification. Dans mon cas, je l'implémente généralement dans l'adaptateur.
la source
J'ai découvert qu'un moyen très simple de recharger le RecyclerView est d'appeler
Cela supprimera d'abord tout le contenu de RecyclerView, puis l'ajoutera à nouveau avec les valeurs mises à jour.
la source
j'ai la réponse après un long moment
la source
Si rien mentionné dans les commentaires ci-dessus ne fonctionne pour vous. Cela pourrait signifier que le problème se situe ailleurs.
Un endroit où j'ai trouvé la solution était dans la façon dont je définissais la liste sur l'adaptateur. Dans mon activité, la liste était une variable d'instance et je la modifiais directement lorsque des données changeaient. Comme il s'agissait d'une variable de référence, il se passait quelque chose de bizarre. J'ai donc changé la variable de référence en une variable locale et utilisé une autre variable pour mettre à jour les données, puis passer à la
addAll()
fonction mentionnée dans les réponses ci-dessus.la source