使用Picasso获得带位图的回调


83

我正在使用Picasso为我的应用下载图像。

我处于需要将第Bitmap一个加载到中之前对其进行访问的情况ImageViewDownloader.Response该类的存在似乎表明这是可能的,但是我找不到任何使用示例。如果可以使用毕加索,我不想编写更多代码来异步处理这一特殊情况。

谁能告诉我该怎么做?


Answers:


172

万一有人怀疑,请在github上找到答案:

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

该帖子建议不要使用匿名回调,而应使用target的实例变量。


30
理想情况下,您将Target直接在视图或视图持有者对象上实现。如果您不这样做,则需要在某个地方维护对该实例的强引用,否则它将被垃圾回收。
杰克·沃顿

@JakeWharton:如果我想对a的每个项目应用自定义动画 ListView,则建议您执行以下操作:private static ViewHolder { private ImageView imageView; private Target target = new Target() { public void onBitmapLoaded() { // do animation on imageView } } }
mbmc 2014年

@JakeWharton在最后的评论中在github.com/square/picasso/issues/308进行了解释。
toobsco42 2014年

8
在onPrepareLoad之后首次调用onBitmapLoaded
Amit Thaper

谢谢你的例子。我只是在onDestroy中错过了一个超级电话。
Ben Groot 2014年

68

这里取下:

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

更新(2016年5月4日):

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

                    }
                });

更新(2016年11月22日)

或使用强大的参考资料Target以免被垃圾收集

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

科特林

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?) {

                  }
                }

6
匿名目标可以被垃圾回收
Steve M

@SteveM那会做什么?取消请求?防止位图加载?
nurettin

@nurettin我假设毕加索(或Glide)对目标有某种弱引用。因此,如果它是匿名的,则没有硬性参考,并且容易受到GC的攻击。当Picasso检查引用时,它将为null,因此不会调用该回调。
史蒂夫·M

因此,这种解决方案确实很糟糕,因为GC有时可能在回调的加载和调用之间运行,并导致回调不被调用。
史蒂夫·M

@SteveM我在Google Play上托管了一个应用程序,该应用程序在其列表视图的滚动过程中在任何情况下至少有2000个用户加载了一堆图标,并使用此方法缩放了一些图标,但我没有看到任何抱怨,评论(我收到了很多)或关于未加载图标的崩溃报告。因此,至少在轶事上,由于某种原因它没有得到垃圾收集。
nurettin

7

什么比下一个容易:

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

应该从不是主线程调用!

或使用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)

我使用了毕加索v.2.5.2


2

我以为也许有些人想要上述答案的RxJava版本...这是:

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

PS订阅时,请将订阅参考存储在您的活动中,否则,目标将在收到响应之前进行GC处理。


似乎此代码现在无法在最新的RxAndroid上使用
Pavandroid
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.