5

I am having the same problem, that I want to use the drawables that are generated by the Picasso for Image Caching Purpose, but I am not able to get the same. Here is the code which I am using to access the Bitmap Drawables :

Target targetBitmap = new Target() {

            @Override
            public void onPrepareLoad(Drawable arg0) {

            }

            @Override
            public void onBitmapLoaded(Bitmap arg0, Picasso.LoadedFrom arg1) {
                mBitmap = arg0;
                BitmapDrawable d = new BitmapDrawable(context.getResources(), arg0);

                int margin = 2;
                int border = 0;

                Rect r = new Rect(margin, margin, width - margin, height - margin);

                int imageWidth = r.width();
                int imageHeight = r.height();

                if (imageHeight > r.height() - (border * 2)) {
                    imageHeight = r.height() - (border * 2);
                }

                r.left += ((r.width() - imageWidth) / 2) - border;
                r.right = r.left + imageWidth + border + border;
                r.top += ((r.height() - imageHeight) / 2) + border;
                r.bottom = r.top + imageHeight + border + border;

                Paint p = new Paint();
                p.setColor(0xFFFFFF);

                c.drawRect(r, p);
                r.left += border;
                r.right -= border;
                r.top += border;
                r.bottom -= border;
                d.setBounds(r);
                d.draw(c);
            }

            @Override
            public void onBitmapFailed(Drawable arg0) {

            }
        };

        Picasso.with(context).load(app.getListBookDetails().get(img_num).getImage_150x225()).into(targetBitmap);

But here onBitmapLoaded method is never called. How can I access this method ? Please help if you can. I have scratched everything but has gone all in vain.

Thanks Sanat

Sanat Pandey
  • 4,081
  • 17
  • 75
  • 132
  • if you add, before the picasso call, the line `Log.d("myapp", app.getListBookDetails().get(img_num).getImage_150x225());` what does it says ? – Budius Sep 22 '14 at 13:14
  • It shows me the Image URL for which I had used picasso. – Sanat Pandey Sep 22 '14 at 13:26
  • Does your app have network permission? Put – Budius Sep 22 '14 at 13:28
  • Yes ofcourse Image is showing when I don't use Picasso, but I have to cache it in Disk thats why I want to use the same. – Sanat Pandey Sep 22 '14 at 13:37
  • can you please post the exact string that Log showed? ps.: Picasso already does Disk cache for you. – Budius Sep 22 '14 at 14:09
  • 12
    If that is your exact code, `targetBitmap` is going to be garbage collected because Picasso is holding a weak reference to it. You need to move it to be a field or implemented on a view or something to prevent this from happening. – Jake Wharton Sep 22 '14 at 14:16
  • Following Jakes advice I tried making Target targetBitmap as a global variable and then call targetBitmap= new Target() {....more code here... } ; This worked though not sure if this is the best approach. – Pranaysharma Apr 10 '15 at 02:34
  • Possible duplicate of [onBitmapLoaded of Target object not called on first load](http://stackoverflow.com/questions/24180805/onbitmaploaded-of-target-object-not-called-on-first-load) – Eugen Pechanec Sep 30 '15 at 20:51

2 Answers2

6

Here is the sample code in case you want to prevent Target object from being garbage collected:

 final Target mTarget = new Target() {
                        @Override
                        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
                            Log.d("DEBUG", "onBitmapLoaded");
                            BitmapDrawable mBitmapDrawable = new BitmapDrawable(getResources(), bitmap);
                            navigationMenuItem.setIcon(mBitmapDrawable);
                        }

                        @Override
                        public void onBitmapFailed(Drawable drawable) {
                            Log.d("DEBUG", "onBitmapFailed");
                        }

                        @Override
                        public void onPrepareLoad(Drawable drawable) {
                            Log.d("DEBUG", "onPrepareLoad");
                        }
                    };


                    Picasso.with(this).load(tempUrl).into(mTarget);
Shubham AgaRwal
  • 4,355
  • 8
  • 41
  • 62
  • @AdamJohns i have made the Target object final to prevent it from being garbage collected – Shubham AgaRwal Apr 29 '16 at 15:53
  • This is not going to work: `final` means that the local variable is unchangable at the language level, but this does not prevent the referenced object to be collected by concurrent GC when the variable's visibility scope ends. – Miha_x64 Mar 26 '17 at 19:52
  • please check it's scope is not local it's instance variable @Miha_x64 So it will not be marked by GC as said by JW in comments – Shubham AgaRwal Mar 26 '17 at 22:46
  • 1
    @Shubham it's not clear from your code. `final Target mTarget = ...` should be a class field — okay, but, first, from class scope, `navigationMenuItem` variable could be unreacable; second, `Picasso.with(...)...` stands along with `final Target target` and nothing says that these parts of code must be located in different places (mTarget in class body, `Picasso.with(...)` — in method body; third, if `mTarget` is a field, it mustn't be `final`, it must be nulled out to be GCed when not needed anymore. – Miha_x64 Mar 27 '17 at 10:26
0

In order to get Bitmap use next 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)
Prilaga
  • 818
  • 10
  • 18
  • There is a problem with the `get()` method: it's result is not cached: > Note: The result of this operation is not cached in memory because the underlying Cache implementation is not guaranteed to be thread-safe. – cVoronin Jul 10 '19 at 17:46
  • @cVoronin thanks for the comment. In my case all is working properly. Did you try to change the cache implementation. I found that cache is saved in the local storage. – Prilaga Jul 12 '19 at 10:34