I have a RecyclerView with a GridLinearLayout and a custom adapter. The content of each item is a picture downloaded using a json and parsing it.
Basically is a grid of pictures.
Everything works almost fine, but however, when scrolling down the content, and the going up again, it shows the previous views in each item for less than a second, and then show the proper picture again.
What could I do to prevent or fix this? Thanks in advance for any help and/or guidance you could provide.
This is the adapter code:
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;
}
}
}
Overwrite onViewRecycled (VH holder)
to set the image to null.
Like this:
public void onViewRecycled (VH holder) {
holder.wall.setImageBitmap(null);
}
As the name suggests RecyclerView
recycles the views to optimize memory so it displays the content of previous view. Since you are loading the image from internet it takes little time to load the image so the content of previous image could be observed. You can do one of the following things.
1) Set a default image from local resource before loading actual image, preferably a small size image to preserve memory.something like this
//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) Set the ImageView
visibility to GONE/INVISIBLE before loading the image and make it VISIBLE again after the image is loaded.
//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);
}
}
}
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With