android - poner - RecyclerView parpadea después de notifyDatasetChanged()
recyclerview fragment tutorial (14)
De acuerdo con esta página de issue ... es la animación de cambio de elemento de vista de reciclaje predeterminada ... Puede desactivarla ... intente esto
recyclerView.getItemAnimator().setSupportsChangeAnimations(false);
Cambiar en la última versión
Citado del blog de desarrolladores de Android :
Tenga en cuenta que esta nueva API no es compatible con versiones anteriores. Si anteriormente implementó un ItemAnimator, en su lugar puede extender SimpleItemAnimator, que proporciona la API anterior envolviendo la nueva API. También notará que algunos métodos se han eliminado por completo de ItemAnimator. Por ejemplo, si estaba llamando a recyclerView.getItemAnimator (). SetSupportsChangeAnimations (false), este código ya no se compilará. Puedes reemplazarlo con:
ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); }
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 del 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 recyclerView, parpadea durante un tiempo muy breve al principio, lo que parece extraño.
Simplemente utilicé GridView / ListView en su lugar 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?
El uso de métodos apropiados de vista de reciclaje para actualizar las vistas resolverá este problema
Primero, haga cambios en la lista
mList.add(item);
or mList.addAll(itemList);
or mList.remove(index);
Luego notifique usando
notifyItemInserted(addedItemIndex);
or
notifyItemRemoved(removedItemIndex);
or
notifyItemRangeChanged(fromIndex, newUpdatedItemCount);
Espero que esto ayude !!
En Kotlin puede usar ''extensión de clase'' para RecyclerView:
fun RecyclerView.disableItemAnimator() {
(itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false
}
// sample of using in Activity:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
myRecyclerView.disableItemAnimator()
// ...
}
Esto simplemente funcionó:
recyclerView.getItemAnimator().setChangeDuration(0);
Hola @ Ali, puede que sea tarde la repetición. También me enfrenté a este problema y lo resolví con la solución a continuación, puede ayudarlo a verificar.
La clase LruBitmapCache.java se crea para obtener el tamaño de caché de imagen
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;
public class LruBitmapCache extends LruCache<String, Bitmap> implements
ImageCache {
public static int getDefaultLruCacheSize() {
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
return cacheSize;
}
public LruBitmapCache() {
this(getDefaultLruCacheSize());
}
public LruBitmapCache(int sizeInKiloBytes) {
super(sizeInKiloBytes);
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
@Override
public Bitmap getBitmap(String url) {
return get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}
VolleyClient.java singleton class [extiende la Aplicación] agregada debajo del código
en el constructor de clase Singleton de VolleyClient, agregue el fragmento a continuación para inicializar el ImageLoader
private VolleyClient(Context context)
{
mCtx = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,getLruBitmapCache());
}
Creé el método getLruBitmapCache () para devolver LruBitmapCache
public LruBitmapCache getLruBitmapCache() {
if (mLruBitmapCache == null)
mLruBitmapCache = new LruBitmapCache();
return this.mLruBitmapCache;
}
Espero que te ayude.
Intente usar ID estables en su RecyclerView.
setHasStableIds(true)
y reemplaza
getItemId(int position)
.
Sin ID estables, después de
notifyDataSetChanged()
, los ViewHolders generalmente se asignan a posiciones no iguales.
Esa fue la razón de parpadear en mi caso.
Puedes encontrar una buena explicación aquí.
Intente usar el stableId en la vista de reciclador. El siguiente artículo lo explica brevemente
Recyclerview utiliza DefaultItemAnimator como animador predeterminado. Como puede ver en el siguiente código, cambian el alfa del titular de la vista al cambiar el elemento:
@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
...
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
...
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
if (newHolder != null) {
....
ViewCompat.setAlpha(newHolder.itemView, 0);
}
...
return true;
}
Quería retener el resto de las animaciones pero eliminé el "parpadeo", así que cloné DefaultItemAnimator y eliminé las 3 líneas alfa anteriores.
Para usar el nuevo animador solo llame a setItemAnimator () en su RecyclerView:
mRecyclerView.setItemAnimator(new MyItemAnimator());
Suponiendo que
mItems
es la colección que respalda su
Adapter
, ¿por qué está eliminando todo y volviendo a agregar?
Básicamente le está diciendo que todo ha cambiado, por lo que RecyclerView vuelve a vincular todas las vistas de lo que supongo que la biblioteca de imágenes no lo maneja correctamente donde todavía restablece la vista, aunque sea la misma URL de imagen.
Tal vez tenían una solución horneada para AdapterView para que funcione bien en GridView.
En lugar de llamar a
notifyDataSetChanged
lo que provocará volver a vincular todas las vistas, llame a eventos de notificación granulares (notificación agregada / eliminada / movida / actualizada) para que RecyclerView vuelva a vincular solo las vistas necesarias y nada parpadeará.
Tengo el mismo problema al cargar la imagen de algunas URL y luego imageView parpadea. Resuelto usando
notifyItemRangeInserted()
en vez de
notifyDataSetChanged()
que evita recargar esos datos antiguos sin cambios.
Tuve un problema similar y esto funcionó para mí. Puede llamar a este método para establecer el tamaño del caché de imágenes
private int getCacheSize(Context context) {
final DisplayMetrics displayMetrics = context.getResources().
getDisplayMetrics();
final int screenWidth = displayMetrics.widthPixels;
final int screenHeight = displayMetrics.heightPixels;
// 4 bytes per pixel
final int screenBytes = screenWidth * screenHeight * 4;
return screenBytes * 3;
}
intente esto para deshabilitar la animación predeterminada
ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}
esta es la nueva forma de deshabilitar la animación ya que el soporte para Android 23
esta antigua forma funcionará para la versión anterior de la biblioteca de soporte
recyclerView.getItemAnimator().setSupportsChangeAnimations(false)
para mí
recyclerView.setHasFixedSize(true);
trabajó
para mi aplicación, tuve algunos cambios de datos, pero no quería que toda la vista parpadeara.
Lo resolví solo desvaneciendo la vista anterior en 0.5 alfa y comenzando la nueva vista alfa en 0.5. Esto creó una transición de desvanecimiento más suave sin hacer que la vista desaparezca por completo.
Desafortunadamente debido a implementaciones privadas, no pude subclasificar el DefaultItemAnimator para hacer este cambio, así que tuve que clonar el código y hacer los siguientes cambios
en animado Cambiar:
ViewCompat.setAlpha(newHolder.itemView, 0); //change 0 to 0.5f
en animateChangeImpl:
oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { //change 0 to 0.5f