Intentando averiguar cuál es el problema con la actualización RecyclerView
del Adaptador.
Después de obtener una nueva Lista de productos, intenté:
Actualice el
ArrayList
desde el fragmento donderecyclerView
se crea, establezca nuevos datos en el adaptador, luego llameadapter.notifyDataSetChanged()
; No funcionó.Cree un nuevo adaptador, como lo hicieron otros, y funcionó para ellos, pero no hay cambio para mí:
recyclerView.setAdapter(new RecyclerViewAdapter(newArrayList))
Cree un método en el
Adapter
que actualice los datos de la siguiente manera:public void updateData(ArrayList<ViewModel> viewModels) { items.clear(); items.addAll(viewModels); notifyDataSetChanged(); }
Luego llamo a este método cada vez que quiero actualizar la lista de datos; No funcionó.
Para verificar si puedo modificar el recyclerView de alguna manera, e intenté eliminar al menos un elemento:
public void removeItem(int position) { items.remove(position); notifyItemRemoved(position); }
Todo quedó como estaba.
Aquí está mi adaptador:
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);
}
}
E inicio de la RecyclerView
siguiente manera:
recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 5));
adapter = new RecyclerViewAdapter(items);
adapter.setOnItemClickListener(this);
recyclerView.setAdapter(adapter);
Entonces, ¿cómo actualizo los datos del adaptador para mostrar los elementos recién recibidos?
Actualización: el problema era que el diseño donde se veía gridView era el siguiente:
<?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>
Luego simplemente eliminé LinearLayout
e hice FrameLayout
como diseño principal.
fuente
items.clear(); items.addAll(newItems);
Es un patrón feo. Si realmente necesita una copia defensiva aquí,items = new ArrayList(newItems);
sería menos feo.Respuestas:
Estoy trabajando con RecyclerView y tanto la eliminación como la actualización funcionan bien.
1) ELIMINAR: hay 4 pasos para eliminar un elemento de un RecyclerView
Esta línea de códigos me funciona.
2) ACTUALIZAR LOS DATOS: lo único que tuve que hacer es
Tuviste que hacer todo esto en el código Actvity / Fragment no en el código del adaptador RecyclerView.
fuente
recycler.removeViewAt(position);
(o más bienrecycler.removeAllViews()
) fueron las cruciales.Esta es una respuesta general para futuros visitantes. Se explican las diversas formas de actualizar los datos del adaptador. El proceso incluye dos pasos principales cada vez:
Insertar elemento individual
Agregue "Pig" en el índice
2
.Insertar elementos múltiples
Inserte tres animales más en el índice
2
.Eliminar un solo artículo
Eliminar "Pig" de la lista.
Eliminar varios elementos
Elimina "Camel" y "Sheep" de la lista.
Eliminar todos los artículos
Borra toda la lista.
Reemplazar lista anterior con lista nueva
Borre la lista anterior y luego agregue una nueva.
El
adapter
tiene una referencia adata
, por lo que es importante que no se estableciódata
a un nuevo objeto. En cambio, borré los elementos antiguosdata
y luego agregué los nuevos.Actualizar elemento individual
Cambie el elemento "Ovejas" para que diga "Me gustan las ovejas".
Mover un solo elemento
Mueva "Sheep" de una posición
3
a otra1
.Código
Aquí está el código del proyecto para su referencia. El código del adaptador RecyclerView se puede encontrar en esta respuesta .
MainActivity.java
Notas
notifyDataSetChanged()
, no se realizará ninguna animación. Esto también puede ser una operación costosa, por lo que no se recomienda su usonotifyDataSetChanged()
si solo está actualizando un solo elemento o una gama de elementos.Estudio adicional
fuente
Update single item
, debería haber sido como las tortugasEsto es lo que funcionó para mí:
Después de crear un nuevo adaptador que contiene la lista actualizada (en mi caso, era una base de datos convertida en una ArrayList) y configurarlo como adaptador, lo intenté
recyclerView.invalidate()
y funcionó.fuente
YourAdapter adapter = (YourAdapter) recyclerView.getAdapter(); adapter.yourSetterMethod(newList); adapter.notifyDataSetChanged();
Dicho esto, parece que lo que el OP intentó primero (solo agregue esto como un comentario para que pueda ayudar a alguien más, ya que eso funcionó en mi caso).tiene 2 opciones para hacer esto: actualizar la interfaz de usuario desde el adaptador:
o actualizarlo desde el reciclador Ver sí mismo:
fuente
Otra opción es usar diffutil . Comparará la lista original con la nueva lista y usará la nueva lista como la actualización si hay un cambio.
Básicamente, podemos usar DiffUtil para comparar los datos antiguos con los nuevos y dejar que llame a notifyItemRangeRemoved, y notifyItemRangeChanged y notifyItemRangeInserted en su nombre.
Un ejemplo rápido del uso de diffUtil en lugar de notifyDataSetChanged:
Hago el trabajo CalculateDiff fuera del hilo principal en caso de que sea una lista grande.
fuente
getItems()
. ¿Cómo sabe qué datos de la lista original deben eliminarse / agregarse / actualizarse?Actualizar datos de vista de lista, vista de cuadrícula y vista de reciclado
o
fuente
La mejor y la mejor manera de agregar nuevos datos a los datos actuales es
fuente
He resuelto el mismo problema de una manera diferente. No tengo datos, los estoy esperando desde el hilo de fondo, así que comience con una lista de emty.
Eso es.
fuente
Estos métodos son eficientes y buenos para comenzar a usar un básico
RecyclerView
.Puede implementarlos dentro de una Clase de adaptador o en su Fragmento o Actividad, pero en ese caso debe crear una instancia del Adaptador para llamar a los métodos de notificación. En mi caso, generalmente lo implemento en el adaptador.
fuente
Descubrí que una forma realmente simple de recargar el RecyclerView es simplemente llamar
Esto eliminará primero todo el contenido de RecyclerView y luego lo agregará nuevamente con los valores actualizados.
fuente
recibí la respuesta después de mucho tiempo
fuente
Si nada de lo mencionado en los comentarios anteriores funciona para usted. Podría significar que el problema se encuentra en otro lugar.
Un lugar donde encontré la solución fue en la forma en que estaba configurando la lista para el adaptador. En mi actividad, la lista era una variable de instancia y la estaba cambiando directamente cuando cambiaba cualquier dato. Debido a que es una variable de referencia, sucedía algo extraño. Así que cambié la variable de referencia a una local y usé otra variable para actualizar los datos y luego pasar a
addAll()
función mencionada en las respuestas anteriores.fuente