Picasso 的 onBitmapLoaded 方法未被调用

5

我有同样的问题,我想使用Picasso生成的可绘制对象来进行图像缓存,但是我无法获取相同的结果。以下是我用于访问位图可绘制对象的代码:

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);

但是这里的 onBitmapLoaded 方法从未被调用。我该如何访问这个方法?如果您能帮忙,我将不胜感激。我已经尝试了所有方法,但都无济于事。

谢谢 Sanat


如果在 Picasso 调用之前添加以下行:Log.d("myapp", app.getListBookDetails().get(img_num).getImage_150x225());,它会输出什么? - Budius
它向我显示了我使用 Picasso 的图像 URL。 - Sanat Pandey
你的应用程序有网络权限吗?请放心。 - Budius
当然,如果我不使用Picasso,图片就会显示出来,但是我必须将其缓存到磁盘中,这就是为什么我想使用它的原因。 - Sanat Pandey
12
如果这是你确切的代码,targetBitmap 将会被垃圾回收,因为 Picasso 持有一个对它的弱引用。你需要将其移到一个字段或实现在视图上,以防止这种情况发生。 - Jake Wharton
显示剩余3条评论
2个回答

6
以下是示例代码,以防止目标对象被垃圾回收:
 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);

@AdamJohns 我已经将Target对象设为final,以防止它被垃圾回收。 - Shubham AgaRwal
这是行不通的:final 意味着局部变量在语言级别上是不可改变的,但这并不能防止被引用的对象在变量的可见范围结束时被并发 GC 收集。 - Miha_x64
请检查它的范围是否为实例变量@Miha_x64,正如JW在评论中所说,它不会被GC标记。 - Shubham AgaRwal
1
@Shubham,从你的代码中并不清楚。final Target mTarget = ... 应该是一个类字段 - 好的,但首先,在类范围内,navigationMenuItem 变量可能无法访问;其次,Picasso.with(...)...final Target target 并列,没有任何东西表明这些代码部分必须位于不同的位置(mTarget 在类体中,Picasso.with(...) - 在方法体中);第三,如果 mTarget 是一个字段,它就不能是 final 的,当不再需要时,它必须被置空以便进行垃圾回收。 - Miha_x64

0

为了使用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)
    }
}

获取位图:

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

注意:由于底层缓存实现不能保证线程安全,此操作的结果未被缓存在内存中。 - cVoronin
@cVoronin 感谢您的评论。在我的情况下一切都正常工作。您是否尝试更改缓存实现方式?我发现缓存保存在本地存储中。 - Prilaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接