I am trying to use RecylerView
which Google introduced recently. I have a set of rows there, 7-8 for now, and each row has a image which I am getting from server. For this I am using Picasso library but this is not working for me. I am not sure if I am missing something or configure something.
The screen is correctly showing the default image on each row but doesn't download image from server and I wait more than 5 minutes if slow response from server but that is not the case.
Code
public DemoRecyclerAdapter(List<DemoRowModel> items, int itemLayout, final Context mContext) {
this.items = items;
this.itemLayout = itemLayout;
this.mContext = mContext;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
DemoRowModel item = items.get(position);
holder.mDemoNameTextView.setText(item.getDemoName());
holder.mDemoDateTextView.setText(item.getDemoDate());
Target mTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
holder.mImageView.setImageBitmap(bitmap);
}
@Override
public void onBitmapFailed(Drawable drawable) {
Logger.d(TAG, "Failed! Bitmap could not downloaded.");
}
@Override
public void onPrepareLoad(Drawable drawable) {
}
};
Picasso.Builder builder = new Picasso.Builder(mContext);
Picasso picasso = builder.downloader(new OkHttpDownloader(mContext) {
@Override
protected HttpURLConnection openConnection(Uri uri) throws IOException {
HttpURLConnection connection = super.openConnection(uri);
// fetch the auth value
SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext.getApplicationContext());
connection.setRequestProperty(Constant.HEADER_X_API_KEY, mSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
return connection;
}
}).build();
picasso.load(item.getImagePath()).into(mTarget);
// here set the value
holder.itemView.setTag(item);
}
Thanks in advance.
If you are using Target
's - they should be strong referenced objects. Create field mTaget
in your class and move Target
's initialization from onBindViewHolder
method.
Edit: hold auth keys in secure place, like keystore
. Don't save them in SharedPreferences
, it's a bad practice.
Update:
1) create custom Target class
public class CommonImageTarget implements Target {
private final ImageView imageView;
public CommonImageTarget(final ImageView imageView) {
this.imageView = imageView;
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
this.imageView.setImageBitmap(bitmap);
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
Logger.d(TAG, "Failed! Bitmap could not downloaded.");
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
2) create custom ImageView
public class ImageViewWithTarget extends ImageView{
/**
* Required for Bitmap loading using Picasso. Picasso uses weak references in into() method and Target's are garbage collected, save them in object.
*/
private Target target;
public ImageViewWithTarget(Context context) {
super(context);
}
public ImageViewWithTarget(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ImageViewWithTarget(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public Target getTarget() {
return target;
}
public void setTarget(Target target) {
this.target = target;
}
}
3) when you initialize your imageView in viewHolder, set custom Target
in it
viewHolder.mImageView.setTarget(new CommonImageTarget(viewHolder.mImageView));
4) update ViewHolder
class
public class ViewHolder{
...
private ImageViewWithTarget mImageView;
}
5) replace ImageView
with ImageViewWithTarget
in your layout
6) update onBindViewHolder
method
picasso.load(item.getImagePath()).into(viewHolder.mImageView.getTarget());
Now every ImageView
will hold own Target
object, and Target
isn't garbage collected.
Another way: hold Target
object in ViewHolder
.