tutorial recyclerview poner implement dentro cardview android android-fragments android-recyclerview

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í.



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