quantumpotato
quantumpotato

Reputation: 9767

Loading image with Picasso does not always display

I'm trying to load an image into my view. Sometimes it works, sometimes it does not. I'm testing on an API level 19 emulator. The failure block inside of the new Target is never called. I see prepareLoad and then either:

  1. onBitmapLoaded is called, the image will show
  2. The image will not show

Why would this be happening?

This is occurring on the emulator. On a physical device, Q&A has reported 100% failure rate. On other devices I see intermittent failure rate. What's going on here?

public void setBackground() {
    final LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);

    final Context context = this;
    final String imagePath = getStore().backgroundImageURI;    

    if (getStore().backgroundImageNumber > 0) {
        mainLayout.setBackground(context.getResources().getDrawable(getStore().backgroundImageNumber));
        return;
    }
    if (imagePath == null) {
        mainLayout.setBackground(context.getResources().getDrawable(R.drawable.sk_collection_bg_default));
        return;
    }
    Picasso.with(this).load(imagePath).into(new Target(){
        @Override
        public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
            Log.v("Biscuit-width", String.valueOf(bitmap.getWidth()));
            Log.v("Biscuit-height", String.valueOf(bitmap.getHeight()));

            mainLayout.setBackground(new BitmapDrawable(context.getResources(), bitmap));
        }

        @Override
        public void onBitmapFailed(final Drawable errorDrawable)
        {
            Log.d("BISCUIT", "FAILED" + errorDrawable.toString());

        }

        @Override
        public void onPrepareLoad(final Drawable placeHolderDrawable) {
            Log.d("TAG", "Prepare Load");
        }
    });
}

Upvotes: 2

Views: 887

Answers (2)

Martin Marconcini
Martin Marconcini

Reputation: 27236

I haven't used Picasso in a while, but back in the day, Targets were WeakReferences, and you had to keep a hard reference to it (forgive me if this is no longer the case, but Jake Wharton was very adamant about the "YOU HAVE TO KEEP A HARD REFERENCE OR TARGET WILL BE GARBAGE COLLECTED" thing; likely because he was asked the same thing over 9000 times (myself included).

So take a look at this stack overflow response to what appears to be the same problem…

https://stackoverflow.com/a/26918731/2684

As noted by the other respondents (@lukas and @mradzinski), Picasso only keeps a weak reference to the Target object. While you can store a strong reference Target in one of your classes, this can still be problematic if the Target references a View in any manner, since you'll effectively also be keeping a strong reference to that View as well (which is one of the things that Picasso explicitly helps you avoid).

If you are in this situation, I'd recommend tagging the Target to the View.

Upvotes: 3

Naveed Akhtar
Naveed Akhtar

Reputation: 131

I am also face this problem, You should use picasso like...

Picasso.Builder builder = new Picasso.Builder(this);
        builder.listener(new Picasso.Listener()
        {
            @Override
            public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception)
            {
                exception.printStackTrace();
            }
        });
        builder.build().load(imgURL)
        .placeholder(R.drawable.ic_launcher)
        .into(imageIMG);

Upvotes: 0

Related Questions