RecyclerView parpadea después de notifyDatasetChanged ()

Tengo un RecyclerView que carga algunos datos de la API, incluye una url de la imagen y algunos datos, y yo uso networkImageView a la imagen perezosa de la carga.

@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 cuando tenemos refresco en el recyclerView, es blincking para un muy corto tiempo en el principio que parece extraño.

Acabo de usar GridView / ListView en su lugar y funcionó como esperaba. No había blincking.

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 que se enfrenta a tal problema? ¿Cuál podría ser la razón?

Intente usar identificadores estables en su RecyclerView.Adapter

setHasStableIds(true) y reemplazar getItemId(int position) .

Sin identificadores estables, después de notifyDataSetChanged() , ViewHolders generalmente asignados a no a las mismas posiciones. Esa fue la razón de que parpadee en mi caso.

De acuerdo con esta página de problema …. es el elemento de recycleview por defecto cambiar la animación … Puede apagarlo .. intente esto

 recyclerView.getItemAnimator().setSupportsChangeAnimations(false); 

Cambio en la última versión

Citado desde Android developer blog :

Tenga en cuenta que esta nueva API no es compatible con versiones anteriores. Si implementó anteriormente un ItemAnimator, puede extender SimpleItemAnimator, que proporciona la API antigua al envolver la nueva API. También notará que algunos métodos han sido eliminados completamente de ItemAnimator. Por ejemplo, si llamaba a recyclerView.getItemAnimator (). SetSupportsChangeAnimations (false), este código no se compilará más. Puede reemplazarlo por:

 ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); } 

Esto simplemente funcionó:

 recyclerView.getItemAnimator().setChangeDuration(0); 

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 desactivar la animación desde el soporte de android 23

Esta vieja manera funcionará para la versión más vieja de la biblioteca de la ayuda

 recyclerView.getItemAnimator().setSupportsChangeAnimations(false) 

Suponiendo que mItems es la colección que respalda su Adapter , ¿por qué lo está quitando todo y re-agregando? Usted está básicamente 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 a pesar de que es la url de la misma imagen. Tal vez tenían algunos al horno en solución para AdapterView para que funcione bien en GridView.

En lugar de llamar a notifyDataSetChanged lo que causará volver a enlazar todas las vistas, llame a eventos de notificación granular (notificar agregado / eliminado / movido / actualizado) para que RecyclerView vuelva a vincular sólo las vistas necesarias y nada parpadeará.

Oye @Ali puede ser replay tarde. También me enfrenté a este problema y resuelto con la solución a continuación, puede ayudarle a comprobar.

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 [extends Application] añadido debajo del código

En el constructor de la clase singleton de VolleyClient agregue debajo del fragmento 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 vaya a ayudarte.

Recyclerview utiliza DefaultItemAnimator como su animador predeterminado. Como se puede ver en el código de abajo, 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; } 

Quise conservar el resto de las animaciones pero quitar el "parpadeo" así que cloné DefaultItemAnimator y quité las 3 líneas alfa arriba.

Para usar el nuevo animador, simplemente llame a setItemAnimator () en su RecyclerView:

 mRecyclerView.setItemAnimator(new MyItemAnimator()); 

Tuve un problema similar y esto funcionó para mí Puede llamar a este método para establecer el tamaño de 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; } 

Para mi aplicación, tuve algunos datos cambiando, pero no quería que la vista entera parpadee.

Lo resolví sólo desvaneciendo la vista anterior de 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 desapareciera por completo.

Desafortunadamente debido a las implementaciones privadas, no pude subclase el DefaultItemAnimator para hacer este cambio así que tuve que clonar el código y hacer los cambios siguientes

En animateChange:

 ViewCompat.setAlpha(newHolder.itemView, 0); //change 0 to 0.5f 

En animateChangeImpl:

 oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { //change 0 to 0.5f 

Para mí recyclerView.setHasFixedSize(true); trabajó

Tengo el mismo problema cargando la imagen de algunas urls y imageView parpadea. Resuelto mediante

 notifyItemRangeInserted() 

en lugar de

 notifyDataSetChanged() 

Que evitan recargar los datos antiguos sin cambios.

El uso de los métodos adecuados de recyclerview para actualizar las vistas resolverá este problema

Primero, haga cambios en la lista

 mList.add(item); or mList.addAll(itemList); or mList.remove(index); 

A continuación, notifique

 notifyItemInserted(addedItemIndex); or notifyItemRemoved(removedItemIndex); or notifyItemRangeChanged(fromIndex, newUpdatedItemCount); 

Espero que esto ayude !!

  • Cómo puedo crear un diseño nestedScroll como este?
  • Recyclerview + Proveedor de contenido + CursorLoader
  • Android: entradas en recyclerview
  • ¿Cómo puedo añadir un RecyclerView horizontal dentro de un elemento de lista
  • ¿Hay observadores escritos en RecyclerView.Adapter para saber si el conjunto de datos ha sido cambiado?
  • StaggeredGridLayoutManager reordena los elementos
  • RecyclerView scrollToPosition no dispara scrollListener
  • Métodos del adaptador RecyclerView no llamados
  • Los elementos no tienen el mismo ancho cuando se utiliza RecyclerView GridLayoutManager para establecer el espaciado de columnas por ItemDecoration
  • El desplazamiento automático se produce cuando Horizontal RecyclerView se coloca como un elemento en un RecyclerView vertical
  • Botón de acción flotante que no se muestra sobre la vista de reciclaje (que se encuentra dentro de un DrawerLayout)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.