Tengo un RecyclerView que carga algunos datos de la API, incluye una URL de imagen y algunos datos, y uso networkImageView para cargar la imagen de forma diferida.
@Override
public void onResponse(List<Item> response) {
mItems.clear();
for (Item item : response) {
mItems.add(item);
}
mAdapter.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}
Aquí está la implementación para el adaptador:
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
if (isHeader(position)) {
return;
}
// - get element from your dataset at this position
// - replace the contents of the view with that element
MyViewHolder holder = (MyViewHolder) viewHolder;
final Item item = mItems.get(position - 1); // Subtract 1 for header
holder.title.setText(item.getTitle());
holder.image.setImageUrl(item.getImg_url(), VolleyClient.getInstance(mCtx).getImageLoader());
holder.image.setErrorImageResId(android.R.drawable.ic_dialog_alert);
holder.origin.setText(item.getOrigin());
}
El problema es que cuando tenemos una actualización en la vista de reciclaje, parpadea durante un tiempo muy corto al principio, lo que parece extraño.
En su lugar, solo usé GridView / ListView y funcionó como esperaba. No hubo parpadeo.
configuración para RecycleView en onViewCreated of my Fragment
:
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
mGridLayoutManager = (GridLayoutManager) mRecyclerView.getLayoutManager();
mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return mAdapter.isHeader(position) ? mGridLayoutManager.getSpanCount() : 1;
}
});
mRecyclerView.setAdapter(mAdapter);
¿Alguien se enfrenta a tal problema? ¿Cuál podría ser la razón?
Respuestas:
Intente usar ID estables en su RecyclerView.Adapter
setHasStableIds(true)
y anulargetItemId(int position)
.Sin ID estables, después
notifyDataSetChanged()
, los ViewHolders generalmente asignados no a las mismas posiciones. Esa fue la razón de parpadear en mi caso.Puedes encontrar una buena explicación aquí.
fuente
De acuerdo con esta página de problemas ... es la animación de cambio de elemento de la vista de reciclaje predeterminada ... Puede apagarla ... intente esto
Cambiar en la última versión
Citado del blog de desarrolladores de Android :
fuente
Esto simplemente funcionó:
fuente
code
ItemAnimator animator = recyclerView.getItemAnimator (); if (animador instancia de SimpleItemAnimator) {((SimpleItemAnimator) animador) .setSupportsChangeAnimations (falso); }code
Tengo el mismo problema al cargar la imagen de algunas URL y luego imageView parpadea. Resuelto usando
en vez de
lo que evita volver a cargar esos datos antiguos sin cambios.
fuente
intente esto para deshabilitar la animación predeterminada
esta es la nueva forma de deshabilitar la animación desde el soporte de Android 23
esta forma antigua funcionará para la versión anterior de la biblioteca de soporte
fuente
Suponiendo
mItems
que la colección es la que lo respaldaAdapter
, ¿por qué está eliminando todo y volviendo a agregar? Básicamente, le está diciendo que todo ha cambiado, por lo que RecyclerView vuelve a enlazar todas las vistas de lo que supongo que la biblioteca de imágenes no lo maneja correctamente, donde aún restablece la vista a pesar de que es la misma url de imagen. Tal vez tenían una solución incorporada para AdapterView para que funcione bien en GridView.En lugar de llamar,
notifyDataSetChanged
lo que provocará que se vuelvan a vincular todas las vistas, llame a eventos de notificación granular (notificar agregado / eliminado / movido / actualizado) para que RecyclerView vuelva a vincular solo las vistas necesarias y nada parpadeará.fuente
Recyclerview usa DefaultItemAnimator como su animador predeterminado. Como puede ver en el código a continuación, cambian el alfa del titular de la vista al cambiar el elemento:
Quería conservar el resto de las animaciones pero eliminar el "parpadeo", así que cloné DefaultItemAnimator y eliminé las 3 líneas alfa de arriba.
Para usar el nuevo animador, simplemente llame a setItemAnimator () en su RecyclerView:
fuente
En Kotlin puede usar 'extensión de clase' para RecyclerView:
fuente
Hola @Ali, podría ser una repetición tardía. También enfrenté este problema y lo resolví con la siguiente solución, puede ayudarlo, por favor verifique.
Se crea la clase LruBitmapCache.java para obtener el tamaño de la caché de la imagen
La clase singleton VolleyClient.java [extiende la aplicación] se agregó debajo del código
en el constructor de la clase singleton VolleyClient, agregue el siguiente fragmento para inicializar el ImageLoader
Creé el método getLruBitmapCache () para devolver LruBitmapCache
Espero que te ayude.
fuente
para mi
recyclerView.setHasFixedSize(true);
funcionofuente
En mi caso, ni ninguno de los anteriores ni las respuestas de otras preguntas de stackoverflow que tenían los mismos problemas funcionaron.
Bueno, estaba usando una animación personalizada cada vez que se hacía clic en el elemento, por lo que estaba llamando a notifyItemChanged (int position, Object Payload) para pasar la carga útil a mi clase CustomAnimator.
Tenga en cuenta que hay 2 métodos onBindViewHolder (...) disponibles en RecyclerView Adapter. El método onBindViewHolder (...) que tiene 3 parámetros siempre se llamará antes que el método onBindViewHolder (...) que tenga 2 parámetros.
Generalmente, siempre anulamos el método onBindViewHolder (...) que tiene 2 parámetros y la raíz principal del problema era que estaba haciendo lo mismo, ya que cada vez que se llama a notifyItemChanged (...), nuestro método onBindViewHolder (...) ser llamado, en el que estaba cargando mi imagen en ImageView usando Picasso, y esta fue la razón por la que se estaba cargando nuevamente, independientemente de si estaba desde la memoria o desde Internet. Hasta que se cargó, me mostraba la imagen del marcador de posición, que era la razón por la que parpadeaba durante 1 segundo cada vez que hacía clic en la vista del elemento.
Más tarde, también anulo otro método onBindViewHolder (...) que tiene 3 parámetros. Aquí verifico si la lista de cargas útiles está vacía, luego devuelvo la implementación de superclase de este método; de lo contrario, si hay cargas útiles, solo estoy estableciendo el valor alfa del itemView del titular en 1.
¡Y sí, obtuve la solución a mi problema después de perder un día completo lamentablemente!
Aquí está mi código para los métodos onBindViewHolder (...):
onBindViewHolder (...) con 2 parámetros:
onBindViewHolder (...) con 3 parámetros:
Aquí está el código del método que estaba llamando en onClickListener de viewHolder's itemView en onCreateViewHolder (...):
Nota: Puede obtener esta posición llamando al método getAdapterPosition () de su viewHolder desde onCreateViewHolder (...).
También he anulado el método getItemId (posición int) de la siguiente manera:
y llamé
setHasStableIds(true);
a mi objeto adaptador en actividad.¡Espero que esto ayude si ninguna de las respuestas anteriores funciona!
fuente
En mi caso, hubo un problema mucho más simple, pero puede parecerse mucho al problema anterior. Había convertido un ExpandableListView en un RecylerView con Groupie (usando la función ExpandableGroup de Groupie). Mi diseño inicial tenía una sección como esta:
Con layout_height establecido en "wrap_content", la animación del grupo expandido al grupo colapsado parecía parpadear, pero en realidad solo se estaba animando desde la posición "incorrecta" (incluso después de probar la mayoría de las recomendaciones de este hilo).
De todos modos, simplemente cambiando layout_height a match_parent como este solucionó el problema.
fuente
Tuve un problema similar y esto funcionó para mí.Puede llamar a este método para establecer el tamaño de la caché de imágenes
fuente
para mi aplicación, cambié algunos datos pero no quería que la vista completa parpadeara.
Lo resolví atenuando la vista anterior a 0.5 alfa e iniciando la nueva vista alfa en 0.5. Esto creó una transición de desvanecimiento más suave sin que la vista desapareciera por completo.
Desafortunadamente, debido a implementaciones privadas, no pude subclasificar DefaultItemAnimator para realizar este cambio, así que tuve que clonar el código y realizar los siguientes cambios
en animateChange:
en animateChangeImpl:
fuente
El uso de métodos de reciclaje apropiados para actualizar las vistas resolverá este problema
Primero, realice cambios en la lista
Luego notifique usando
¡Espero que esto ayude!
fuente
Intente usar el stableId en la vista de reciclador. El siguiente artículo lo explica brevemente
https://medium.com/@hanru.yeh/recyclerviews-views-are-blinking-when-notifydatasetchanged-c7b76d5149a2
fuente
Solución de Kotlin:
fuente