在加载图片的场景中,有时需要异步拿到Bitmap做一些操作:bitmap预热、bitmap裁剪等,当加载成功的时候通过回调的形式来获取Bitmap,然后进行处理。Picasso提供了一种回调的方式获取Bitmap。客户端实现Target接口即可在加载成功的时候通过回调的方式返回bitmap。代码如下:
Picasso.with(context).load(url).into(new Target() {
@Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
//加载成功,进行处理
}
@Override public void onBitmapFailed(Drawable errorDrawable) {
//加载失败
}
@Override public void onPrepareLoad(Drawable placeHolderDrawable) {
//开始加载
}
});
通过上面的回调函数,我们就可以获取Bitmap,然后进行bitmap的自定义处理。
但是有时候回调却没有触发,也没有异常,最后开启Picasso日志,才发现target引用被gc掉了:
一、异步回调的陷阱
后面查看源码之后才发现,由于Picasso将target引用包装成了一个弱引用,当gc发生时target引用就很可能被回收从而无法回调。
首先,先看into(target)源码:
public void into(Target target) {
//代码省略....
//将target作为参数,实例化一个targetAction,此处Action表示picasso的一个抽象行为。
Action action = new TargetAction(picasso, target, request, memoryPolicy, networkPolicy, errorequestKey, tag, errorResId);
}
这里我们可以看到,首先picasso会判断是否从内存中读取,如果不从内存中读取,那么就创建一个新的Action任务,将target作为参数给TargetAction持有。重要关注TargetAction这个类,我们再看一看TargetAction类的构造有什么内容:
final class TargetAction extends Action<Target> {
TargetAction(Picasso picasso, Target target, Request data, int memoryPolicy,Drawable errorDrawable, String key, Object tag, int errorResId) {
super(picasso, target, data, memoryPolicy, networkPolicy, errorResId, errorDraw,false);
}
// 代码省略
}
这里可以看到,TargetAction继承了Action类,target引用传给了父类Action的构造函数:
abstract class Action<T> {
//picasso实现的弱引用
static class RequestWeakReference<M> extends WeakReference<M> {
final Acti