【问题标题】:Use Picasso to get a callback with a Bitmap使用 Picasso 获取带有位图的回调
【发布时间】:2013-12-09 11:53:32
【问题描述】:

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

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

谁能告诉我怎么做?

【问题讨论】:

标签: android bitmap picasso


【解决方案1】:

如果有人想知道,请在 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。如果您不这样做,则需要在某处维护对实例的强引用,否则它将被垃圾收集。
  • @JakeWharton:如果我想在ListView 的每个项目上应用自定义动画,你建议这样做:private static ViewHolder { private ImageView imageView; private Target target = new Target() { public void onBitmapLoaded() { // do animation on imageView } } }?
  • @JakeWharton 在最后一条评论中在这里github.com/square/picasso/issues/308 解释。
  • onBitmapLoaded onPrepareLoad 后第一次不调用
  • 感谢您的示例。我只是错过了 onDestroy 中的一个超级调用。
【解决方案2】:

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

更新(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?) {

                  }
                }

【讨论】:

  • 匿名目标可能被垃圾回收
  • @SteveM 那会做什么?取消请求?防止加载位图?
  • @nurettin 我假设毕加索(或 Glide)对目标有某种弱引用。因此,如果它是匿名的,则没有硬引用,并且容易受到 GC 的攻击。当 Picasso 检查引用时,它将为 null,因此不会调用回调。
  • 所以这个解决方案真的很糟糕,因为GC可能偶尔会在回调的加载和调用之间运行,导致回调不被调用。
  • @SteveM 我在 google play 上托管了一个应用程序,该应用程序在其列表视图滚动期间加载一堆图标,在任何情况下至少有 2000 个用户,使用这种方法缩放一些图标,但我没有没有看到任何关于图标未加载的投诉、评论(我收到很多)或崩溃报告。所以至少有趣的是,由于某种原因,它没有收集垃圾。
【解决方案3】:

比下一个更容易:

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)

我使用的是 Picasso v.2.5.2

【讨论】:

    【解决方案4】:

    我想也许你们中的一些人想要上述答案的 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);
            }
        });
    }
    

    附:订阅时,将订阅引用存储在您的活动中,否则,目标将在您收到响应之前被 GC...

    【讨论】:

    • 似乎这段代码现在不适用于最新的 RxAndroid
    猜你喜欢
    • 2014-12-04
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 2014-07-27
    • 2017-01-21
    • 1970-01-01
    相关资源
    最近更新 更多