Alex Alex - 4 months ago 21
Android Question

Picasso Load Image into Target

I'm using Picasso to download various images. Usually, I just display these in an

ImageView
but in this situation, I want to hold a strong reference to them so that I can use them in different places without having to refer back to the cache or re-download them. Here is how I am attempting to do that (note that there is more to this class - I've just narrowed it down to the parts that are relevant to this question):

public class MapLayer {

private Context mContext;
private String mType;
private Drawable mIcon = null;

public MapLayer (Context context, String type) {
mContext = context;
mType = type;
downloadIcon();
}

public Drawable getIcon() {return mIcon;}

private void downloadIcon() {

String url = mContext.getString(R.string.maps_icon_url).replace("${type}", mType));

Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Log.d(TAG, "on bitmap loaded");
mIcon = new BitmapDrawable(mContext.getResources(), bitmap);
}

@Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "on bitmap failed");
}

@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "on prepare load");
mIcon = placeHolderDrawable;
}
};

ImageDownloader.getSharedInstance().load(url).into(target);
}
}


In every case, I get the output:

on prepare load


but nothing else. My icon is always null. I know this from other classes where I call
getIcon()
.

What am I missing here? Thanks for any help.

Answer

Picasso holds Target instance with a weak reference, So your Target seems to be garbage collected.
see: https://github.com/square/picasso/issues/352

It is better to hold Target as an instance field.

public class MapLayer {

    ...

    private Target target;

    private void downloadIcon() {

        ...

        target = new Target() {
            ...
        };

        ImageDownloader.getSharedInstance().load(url).into(target);
    }
}
Comments