Question

I'm using Picasso to download images for my app.

I'm in a situation where I need to access the Bitmap first before it's loaded into the ImageView. The presence of the Downloader.Response class seems to suggest this is possible, but I can't find any use examples. I don't want to write a bunch more code to asynchronously handle this one particular case if it's possible to do with Picasso.

Can anyone show me how to do it?

Was it helpful?

Solution

Found the answer on github in case anyone is wondering:

private Target target = new Target() {
      @Override
      public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
      }

      @Override
      public void onBitmapFailed(Drawable errorDrawable) {
      }

      @Override
      public void onPrepareLoad(Drawable placeHolderDrawable) {
      }
}

private void someMethod() {
   Picasso.with(this).load("url").into(target);
}

@Override 
public void onDestroy() {  // could be in onPause or onStop
   Picasso.with(this).cancelRequest(target);
   super.onDestroy();
}

The post recommends not using an anonymous callback, and instead using an instance variable for target.

OTHER TIPS

taken from here:

Picasso.with(this)
    .load(url)
    .into(new Target() {
        @Override
        public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
            /* Save the bitmap or do something with it here */

            //Set it in the ImageView
            theView.setImageBitmap(bitmap); 
        }
});

Updated (May 04, 2016):

            Picasso.with(this)
                .load(youUrl)
                .into(new Target() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                    }

                    @Override
                    public void onBitmapFailed(Drawable errorDrawable) {

                    }

                    @Override
                    public void onPrepareLoad(Drawable placeHolderDrawable) {

                    }
                });

Updated (November 22, 2016)

or using a strong reference for Target so that it wont be garbage collected

Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };


void foo() {
        Picasso.with(getContext()).load(getUrl()).into(target);
}

Kotlin

object: com.squareup.picasso.Target {
                  override fun onBitmapFailed(e: java.lang.Exception?, errorDrawable: Drawable?) {
                    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
                }

                  override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
                    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
                  }

                  override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {

                  }
                }

What can be easy than next:

val url: String = "https://...."
val bitmap: Bitmap = Picasso.with(context).load(url).get()

Should be called from not the main thread!

or with RxJava 2:

fun getBitmapSingle(picasso: Picasso, url: String): Single<Bitmap> = Single.create {
    try {
        if (!it.isDisposed) {
            val bitmap: Bitmap = picasso.load(url).get()
            it.onSuccess(bitmap)
        }
    } catch (e: Throwable) {
        it.onError(e)
    }
}

Retrieve Bitmap:

getBitmapSingle(Picasso.with(context), "https:/...")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ bitmap ->
                // val drawable = BitmapDrawable(context, bitmap)
                }, Throwable::printStackTrace)

I used Picasso v.2.5.2

I thought maybe some of you would like an RxJava version of the above answer... Here it is:

    public static Observable<Bitmap> loadBitmap(Picasso picasso, String imageUrl) {
    return Observable.create(new Observable.OnSubscribe<Bitmap>() {
        @Override
        public void call(Subscriber<? super Bitmap> subscriber) {
            Target target = new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    subscriber.onNext(bitmap);
                    subscriber.onCompleted();
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                    subscriber.onError(new Exception("failed to load " + imageUrl));
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                }
            };
            subscriber.add(new Subscription() {
                private boolean unSubscribed;

                @Override
                public void unsubscribe() {
                    picasso.cancelRequest(target);
                    unSubscribed = true;
                }

                @Override
                public boolean isUnsubscribed() {
                    return unSubscribed;
                }
            });
            picasso.load(imageUrl).into(target);
        }
    });
}

P.S. When subscribing, store the subscription reference on your activity, otherwise, target will be GC'd before you receive a response...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top