Picasso中加载图片时Targets/Callback不回调

一、问题描述:

在使用Picasso加载图片的时候,有时候我们希望通过Targets/Callback接口来回调,用于对所需图片的处理。但是这个接口会出现有时候没有被回调,导致加载失败!

二、问题原因:

Picasso的Targets/Callback是弱引用,可能被GC回收,也可能没回收,所以回调变成了随机事件。

DeferredRequestCreator(RequestCreator creator, ImageView target, Callback callback) {
    this.creator = creator;
    //target被当成弱引用,来自Picasso源码
    this.target = new WeakReference(target);
    this.callback = callback;
    target.getViewTreeObserver().addOnPreDrawListener(this);
  }

@Override public boolean onPreDraw() {
    //图片下载完后回调,如果target为空,直接返回了
    ImageView target = this.target.get();
    if (target == null) {
      return true;
    }
    ViewTreeObserver vto = target.getViewTreeObserver();
    if (!vto.isAlive()) {
      return true;
    }

    int width = target.getWidth();
    int height = target.getHeight();

    if (width <= 0 || height <= 0) {
      return true;
    }

    vto.removeOnPreDrawListener(this);

    this.creator.unfit().resize(width, height).into(target, callback);
    return true;
  }

三、解决方案:

将Targets/Callback变成强引用,例如以下方法。

// 直接下载图片,需要在work thread
Picasso.with(context).load(url).get();
 
// Callback
ImageView profile = new ImageView(context);
Picasso.with(context).load(URL).into(profile, new Callback() {
    @Override
    public void onSuccess() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {//You will get your bitmap here
 
                Bitmap innerBitmap = ((BitmapDrawable) profile.getDrawable()).getBitmap();
            }
        }, 100);
    }
 
    @Override
    public void onError() {
 
    }
});
 
//or
 
// Target
final List targets = new ArrayList();
for (int i = 0; i < 3; i++) { 
    final int k=i;
    Target target = new Target() {
 
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {                         
            Log.i("load", "Ok " + k);   
            //use bitmap for add marker to map
            targets.remove(this);                
        }
 
        @Override
        public void onBitmapFailed(Drawable errorDrawable) {
            targets.remove(this);
        }
 
        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {
            Log.i("load", "first " + k);
        }
    }
    targets.add(target);
    Picasso.with(this)
        .load(ListA.get(i).getImage()) //image
        .resize(100, 100)
        .transform(new ImageTrans_CircleTransform())
        .into(target);  
}

四、关于Java引用的扩展

强引用: 强引用是Java中最普通的引用,随意创建一个对象然后在其他的地方引用一下,就是强引用,强引用的对象Java宁愿OOM也不会回收他

软引用: 软引用是比强引用弱的引用,在Java gc的时候,如果软引用所引用的对象被回收,首次gc失败的话会继而回收软引用的对象,软引用适合做缓存处理可以和引用队列(ReferenceQueue)一起使用,当对象被回收之后保存他的软引用会放入引用队列

弱引用: 弱引用是比软引用更加弱的引用,当Java执行gc的时候,如果弱引用所引用的对象被回收,无论他有没有用都会回收掉弱引用的对象,不过gc是一个比较低优先级的线程,不会那么及时的回收掉你的对象。 可以和引用队列一起使用,当对象被回收之后保存他的弱引用会放入引用队列

虚引用: 虚引用和没有引用是一样的,他必须和引用队列一起使用,当Java回收一个对象的时候,如果发现他有虚引用,会在回收对象之前将他的虚引用加入到与之关联的引用队列中。可以通过这个特性在一个对象被回收之前采取措施

参考
Target.onBitmapLoaded() method not called the first time after completed (network) request. #352

你可能感兴趣的:(Picasso中加载图片时Targets/Callback不回调)