Recyclerview dolorosamente lento para cargar imágenes en caché de Picasso

He implementado un RecyclerView que contiene principalmente imágenes que se está cargando a través de Picasso. Mi problema es que tan pronto como desplazo hacia abajo o hacia arriba de la vista, la imagen de marcador de posición aparece por aprox. Un segundo antes de ser reemplazado por la imagen real. Se desplaza muy suavemente, pero es prácticamente inutilizable. Esto sucede cada vez que algo se desplaza de la pantalla.

Picasso está claramente almacenando en caché las imágenes en el disco, ya que se cargan más rápido que el tiempo de carga inicial, pero definitivamente se recarga instantáneamente desde la caché. ¿Qué implementé incorrectamente?

Mi código del adaptador:

public class ExploreAdapter extends RecyclerView.Adapter<ExploreAdapter.ExploreViewHolder> { private List<ExploreItem> exploreItemList; private Context mContext; private int deviceWidth = PrefUtils.getDeviceWidth(); public ExploreAdapter(Context context, List<ExploreItem> exploreItemList){ this.mContext = context; this.exploreItemList = exploreItemList; } @Override public int getItemCount(){ return exploreItemList.size(); } @Override public void onBindViewHolder(ExploreViewHolder exploreViewHolder, int i){ ExploreItem item = exploreItemList.get(i); exploreViewHolder.getvTitle().setText(item.getTitle()); exploreViewHolder.getvUsername().setText(item.getUsername()); exploreViewHolder.getvNumLikes().setText(item.getNbOfLikes()); Picasso.with(mContext).load(item.getMediaLocation().trim()) .resize(deviceWidth, deviceWidth) .centerCrop() .placeholder(R.drawable.profile_background) .into(exploreViewHolder.getvImage()); Picasso.with(mContext).load(item.getUserProfilePicUrl().trim()) .placeholder(R.drawable.profile_picture) .into(exploreViewHolder.getvProfilePic()); } @Override public ExploreViewHolder onCreateViewHolder(ViewGroup viewGroup, int i){ View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.explore_item, viewGroup, false); return new ExploreViewHolder(itemView); } public static class ExploreViewHolder extends RecyclerView.ViewHolder{ private TextView vTitle, vUsername, vNumLikes; private SquareImage vImage; private ImageView vProfilePic; public ExploreViewHolder(View v){ super(v); this.vTitle = (TextView) v.findViewById(R.id.explore_item_title); this.vUsername = (TextView) v.findViewById(R.id.explore_item_username); this.vNumLikes = (TextView) v.findViewById(R.id.explore_item_number_likes); this.vImage = (SquareImage) v.findViewById(R.id.explore_item_image); this.vProfilePic = (ImageView) v.findViewById(R.id.explore_item_profile_picture); } public TextView getvTitle() { return vTitle; } public TextView getvUsername() { return vUsername; } public ImageView getvProfilePic() { return vProfilePic; } public SquareImage getvImage() { return vImage; } public TextView getvNumLikes() { return vNumLikes; } public void setvImage(SquareImage vImage) { this.vImage = vImage; } public void setvNumLikes(TextView vNumLikes) { this.vNumLikes = vNumLikes; } public void setvProfilePic(ImageView vProfilePic) { this.vProfilePic = vProfilePic; } public void setvTitle(TextView vTitle) { this.vTitle = vTitle; } public void setvUsername(TextView vUsername) { this.vUsername = vUsername; } } } 

Cualquier ayuda es apreciada.

Configurar los parámetros de recyclerView como a continuación resuelto mi problema de tartamudeo:

 recyclerView.setHasFixedSize(true); recyclerView.setItemViewCacheSize(20); recyclerView.setDrawingCacheEnabled(true); recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); 

Espero que ayude a alguien más también.

Utilice fit() .

 Picasso.with(context) .load(file) .fit() .centerCrop() .into(imageView); 

El fit() realidad redimensiona la imagen para ajustarse a los imageView de imageView . Esto no carga la imagen completa y suaviza el desplazamiento.

He encontrado esta edición recientemente, y sí usted correcto. Picasso es una buena biblioteca para mostrar imágenes de sdcard, pero tiene algunos problemas con respecto a la caché si está buscando imágenes en línea es por eso que ve una imagen de titular de lugar mientras se desplaza. He intentado cosas diferentes y el problema no se resolvió.

Hay una biblioteca alternativa, es decir, "AQuery", que es muy buena para buscar y almacenar en caché las imágenes de la red.

http://code.google.com/p/android-query/

Las principales ventajas de AQuery / Android Query es que puede borrar la memoria caché, no hay retraso mientras se desplaza y es bastante eficaz para almacenar imágenes en caché y no mostrar imágenes de titular de lugar mientras se desplaza.

Resolví mi problema eliminando picaaso y usando Aquery. Es sólo un reemplazo de una línea y ya está hecho con su problema.

 (new AQuery(mContext)).id(exploreViewHolder.getvProfilePic()).image(item.getUserProfilePicUrl().trim(), true, true, device_width, R.drawable.profile_background, aquery.getCachedImage(R.drawable.profile_background),0); 

Además usted puede cambiar fácilmente de picasso a AQuery ya que no hay tal cosa que está disponible en picasso pero no en AQuery y la sintaxis es casi la misma. Así que te recomiendo que utilices AQuery, hasta que esto se corrija por picasso.

Me mezcló la respuesta de @ergunkocak y @Mangesh Ghotage, utilizando esto funciona muy bien:

 recyclerView.setHasFixedSize(true); recyclerView.setItemViewCacheSize(20); recyclerView.setDrawingCacheEnabled(true); 

Y esto en cada imagen:

 Picasso.with(context) .load(file) .fit() .into(imageView); 

Además de que podría configurar Picasso para utilizar una única instancia como esta:

 Picasso.setSingletonInstance(picasso); 

Y, finalmente, la habilitación de los indicadores de caché le dará pistas sobre lo que va mal:

 Picasso .with(context) .setIndicatorsEnabled(true); 

Más sobre Picasso

No puedo verificar la corrección de esta solución, pero yo también estaba enfrentando este problema y me acerqué a ella siguiendo esta idea:

 @Override public void onBindViewHolder(ViewHolder viewHolder, final int i) { ... if(mImageView.getDrawable == null()){ Picasso.with(context) .load(path) .error(errorResId) .tag(tag) .into(mImageView); } ... 

}

Queda prohibido que Picasso cargue nada a menos que ImageView no tenga nada que mostrar.

Picasso almacena automáticamente las imágenes en dos niveles:

  • Caché de disco (esto no es en realidad en picasso sino en la capa de red que picasso usa)
  • Caché de memoria

Se bot inicializado con los valores predeterminados que suites la mayoría de las aplicaciones.

Cuando el caché de memoria se vuelve demasiado grande, el mapa de bits usado más antiguo se elimina del caché de memoria (que por defecto es 1/7 del espacio de montón disponible).

Creo que lo que está sucediendo aquí es que usted está cerca del límite de memoria de la memoria caché y, por lo tanto, las imágenes se decodifican de nuevo cada vez que los necesita de nuevo.

Vea aquí: Android Picasso Configurar el tamaño de LruCache

Pero te aconsejo que NO aumente el tamaño de la memoria caché a menos que realmente estás re-dimensionando las imágenes al tamaño real que usas ..

Creo que el problema con su código es el siguiente:

 .resize(deviceWidth, deviceWidth) 

¿Estás seguro de que realmente necesitas una imagen de ese tamaño? ¿Qué almacenes en PrefUtils? ¿Se actualiza cuando el dispositivo gira? (Paisaje vs retrato)

Si necesita imágenes más pequeñas intente pasar el tamaño real de la imagen que va a utilizar. Si no lo sabes (calculado en tiempo de ejecución con el diseño) hazlo con una aproximación o escribe tu código para obtener el tamaño real (normalmente escribo clases personalizadas extendiendo ImageView para estas cosas).

Si realmente necesita las imágenes en ese tamaño sólo aumentar el tamaño de la caché (ver enlace anterior) y usted debe ser bueno para ir.

Sólo use el atributo noPlaceholder .

  • RecyclerView - ¿Cómo suavizar desplazamiento a la parte superior del elemento en una posición determinada?
  • Desplazar SwipeRefreshLayout con RecyclerView Actualizar en cualquier lugar de android 2.2
  • Cómo decorar selectivamente los elementos de RecyclerView
  • Error al inflar la clase RecyclerView
  • cómo clasificar los datos en RecyclerView
  • Efecto Parallax en cada elemento en una vista de reciclador?
  • SetLayoutManager NullPointException en RecyclerView
  • Pantalla Android Parpadea en mostrar / ocultar barras del sistema
  • Cómo animar los elementos de RecyclerView cuando aparecen
  • Elemento RecyclerView que no muestra ondulaciones / retroalimentación táctil cuando el elemento tiene una casilla de verificación
  • TableLayout Vs Recycler Ver?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.