Evitar que RecyclerView muestre contenido anterior al desplazarse

Tengo un RecyclerView con un GridLinearLayout y un adaptador personalizado. El contenido de cada elemento es una imagen descargada usando un json y analizándolo.

Básicamente es una cuadrícula de imágenes.

Todo funciona casi bien, pero sin embargo, cuando se desplaza hacia abajo el contenido, y la subida de nuevo, muestra las vistas anteriores en cada elemento durante menos de un segundo y, a continuación, mostrar la imagen adecuada de nuevo.

¿Qué puedo hacer para prevenir o solucionar esto? Gracias de antemano por cualquier ayuda y / o orientación que pueda proporcionar.

Este es el código del adaptador:

package jahirfiquitiva.project.adapters; import android.content.Context; import android.graphics.Bitmap; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import jahirfiquitiva.project.activities.WallpapersActivity; import com.koushikdutta.async.future.FutureCallback; import com.koushikdutta.ion.Ion; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import jahirfiquitiva.project.R; public class WallpapersAdapter extends RecyclerView.Adapter<WallpapersAdapter.WallsHolder> { public interface ClickListener { void onClick(WallsHolder view, int index, boolean longClick); } private ArrayList<HashMap<String, String>> data; private final Context context; private boolean usePalette = true; private final ClickListener mCallback; private final Map<String, Palette> mPaletteCache = new WeakHashMap<>(); public WallpapersAdapter(Context context, ClickListener callback) { this.context = context; this.data = new ArrayList<>(); this.mCallback = callback; } public void setData(ArrayList<HashMap<String, String>> data) { this.data = data; notifyDataSetChanged(); } @Override public WallsHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); return new WallsHolder(inflater.inflate(R.layout.wallpaper_item, parent, false)); } @Override public void onBindViewHolder(final WallsHolder holder, int position) { Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in); HashMap<String, String> jsondata = data.get(position); holder.name.setText(jsondata.get(WallpapersActivity.NAME)); final String wallurl = jsondata.get(WallpapersActivity.WALL); holder.wall.startAnimation(anim); holder.wall.setTag(wallurl); Ion.with(context) .load(wallurl) .asBitmap() .setCallback(new FutureCallback<Bitmap>() { @Override public void onCompleted(Exception e, Bitmap result) { holder.progressBar.setVisibility(View.GONE); if (e != null) { e.printStackTrace(); } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) { holder.wall.setImageBitmap(result); if (usePalette) { Palette p; if (mPaletteCache.containsKey(wallurl)) { p = mPaletteCache.get(wallurl); } else { p = new Palette.Builder(result).generate(); mPaletteCache.put(wallurl, p); } if (p != null) { Palette.Swatch wallSwatch = p.getVibrantSwatch(); if (wallSwatch != null) { holder.titleBg.setBackgroundColor(wallSwatch.getRgb()); holder.titleBg.setAlpha(1); holder.name.setTextColor(wallSwatch.getTitleTextColor()); holder.name.setAlpha(1); } } } } } }); } @Override public int getItemCount() { return data.size(); } public class WallsHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { public final View view; public final ImageView wall; public final TextView name; public final ProgressBar progressBar; public final LinearLayout titleBg; WallsHolder(View v) { super(v); view = v; wall = (ImageView) v.findViewById(R.id.wall); name = (TextView) v.findViewById(R.id.name); progressBar = (ProgressBar) v.findViewById(R.id.progress); titleBg = (LinearLayout) v.findViewById(R.id.titlebg); view.setOnClickListener(this); view.setOnLongClickListener(this); } @Override public void onClick(View v) { int index = getLayoutPosition(); if (mCallback != null) mCallback.onClick(this, index, false); } @Override public boolean onLongClick(View v) { int index = getLayoutPosition(); if (mCallback != null) mCallback.onClick(this, index, true); return false; } } } 

Como su nombre indica, RecyclerView recicla las vistas para optimizar la memoria para que muestre el contenido de la vista anterior. Dado que se está cargando la imagen desde Internet, se tarda poco tiempo en cargar la imagen para poder observar el contenido de la imagen anterior. Usted puede hacer una de las siguientes cosas.

1) Establecer una imagen predeterminada de un recurso local antes de cargar la imagen real, preferiblemente una imagen de tamaño pequeño para conservar la memoria. Algo así

 //load default image first holder.wall.setImageResource(R.id.your_default_image_resource); //load actual image Ion.with(context) .load(wallurl) .asBitmap() .setCallback(new FutureCallback<Bitmap>() { @Override public void onCompleted(Exception e, Bitmap result) { holder.progressBar.setVisibility(View.GONE); if (e != null) { e.printStackTrace(); } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) { holder.wall.setImageBitmap(result); if (usePalette) { Palette p; if (mPaletteCache.containsKey(wallurl)) { p = mPaletteCache.get(wallurl); } else { p = new Palette.Builder(result).generate(); mPaletteCache.put(wallurl, p); } if (p != null) { Palette.Swatch wallSwatch = p.getVibrantSwatch(); if (wallSwatch != null) { holder.titleBg.setBackgroundColor(wallSwatch.getRgb()); holder.titleBg.setAlpha(1); holder.name.setTextColor(wallSwatch.getTitleTextColor()); holder.name.setAlpha(1); } } } } } }); 

2) Configure la visibilidad de ImageView en GONE / INVISIBLE antes de cargar la imagen y vuelva a ser VISIBLE después de cargar la imagen.

  //hide the imageview holder.wall.setVisibility(View.INVISIBLE); Ion.with(context) .load(wallurl) .asBitmap() .setCallback(new FutureCallback<Bitmap>() { @Override public void onCompleted(Exception e, Bitmap result) { holder.progressBar.setVisibility(View.GONE); if (e != null) { e.printStackTrace(); } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) { //show the imageview and set bitmap holder.wall.setVisibility(View.VISIBLE); holder.wall.setImageBitmap(result); if (usePalette) { Palette p; if (mPaletteCache.containsKey(wallurl)) { p = mPaletteCache.get(wallurl); } else { p = new Palette.Builder(result).generate(); mPaletteCache.put(wallurl, p); } if (p != null) { Palette.Swatch wallSwatch = p.getVibrantSwatch(); if (wallSwatch != null) { holder.titleBg.setBackgroundColor(wallSwatch.getRgb()); holder.titleBg.setAlpha(1); holder.name.setTextColor(wallSwatch.getTitleTextColor()); holder.name.setAlpha(1); } } } } } }); 

Sobrescribir onViewRecycled (VH holder) para establecer la imagen en null.

Me gusta esto:

 public void onViewRecycled (VH holder) { holder.wall.setImageBitmap(null); } 

Creo que debería agregar lugar titular como este:

 Ion.with(context).load("http://example.com/image.png") .withBitmap() .placeholder(R.drawable.placeholder_image) .error(R.drawable.error_image) .intoImageView(imageView); 

O establecer la imagen predeterminada al principio.

 holder.wall.setImageResource(R.drawable.placeholder_image); 
  • La división de una cadena funciona en Java, no funciona en Android
  • No se puede mostrar la barra del sistema Android después de ocultar
  • Cómo establecer X-Api-Key en el encabezado de la solicitud HTTP obtener
  • Utilizar el mismo fragmento en ViewPager pero el fragmento tendrá un diseño diferente cada vez
  • No se puede agregar el color principal del atributo en android drawable xml
  • Google App Engine - escala automática con siempre en instancia?
  • Código demasiado grande y demasiados errores constantes (Android Studio)
  • Android OkHttp biblioteca: GET Solicitud - Excepción EOFException: \ n no encontrado: size = 0 content =
  • ListView filtrar correctamente pero muestra un resultado incorrecto
  • Textview La gravedad no funciona correctamente en android
  • Android jobScheduler no se detendrá con jobFinished (params, false)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.