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.
- ERROR: "Error de sintaxis en símbolo"; ",, esperado" ¿Por qué?
- Cómo puedo importar java.awt.image.BufferedImage en Android Studio
- Utilice el paquete de un sabor en el manifiesto
- ¿Cómo acceder a la base de datos sqlite existente en Android Emulator?
- Transmitir vídeo en vivo desde la cámara en android
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; } } }
- Cargando parcialmente las imágenes de la URL, como lo que se implementa en WhatsApp
- ¿Cómo se comprueba si ya se ha cerrado una instancia de reino?
- Creación de la notificación de InstrumentationTestCase
- Hora de Joda y error de ProGuard al exportar .apk
- Problema de orden de consultas SQLite de Android
- 'Texture2D': No se encontró ninguna función sobrecargada equivalente OpenGL ES2 Android (JAVA)
- La primera compilación con AndroidStudio falló
- Android - Obtener el nombre de archivo original para una descarga asíncrona
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);
- Referencia de LoaderManager no encontrada con API Nivel 17
- Cómo invitar a los amigos de facebook a través de mi aplicación?