Picasso 框架源码解析

Picasso 简单使用

Picasso.with(context)
.load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
.resize(200,200) 
//占位图,图片加载出来之前显示的默认图片  
.placeholder(R.mipmap.ic_launcher)  
//错误图,图片加载出错时显示的图片  
.error(R.mipmap.ic_launcher)  
.into(ivImg);

Picasso没有对外暴露其构造函数,只能通过Picasso.Builder()建造者模式创建自己的实例。建造者模式将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

Picasso创建

Picasso提供两种方式获得Picasso实例

  • 全局的默认实例
  • 通过Picasso.Builder自己构建Picasso实例
    通过with()方法,可以获取全局的Picasso实例:
static volatile Picasso singleton = null;
public static Picasso with(@NonNull Context context) {
    if (context == null) {
        throw new IllegalArgumentException("context == null");
    }
    if (singleton == null) {
        synchronized (Picasso.class) {
            if (singleton == null) {
                singleton = new Builder(context).build();
            }
        }
    }
    return singleton;
}

Picasso使用标准的双检锁构建线程安全的全局实例,注意静态属性singleton使用volatile修饰保证多线程对singleton的可见性。

Request和Action的创建

Picasso可以加载链接、文件、Uri以及引用自带的res资源

public RequestCreator load(@Nullable Uri uri) {
    return new RequestCreator(this, uri, 0);
}

public RequestCreator load(@Nullable String path) {
    if (path == null) {
        return new RequestCreator(this, null, 0);
    }
    if (path.trim().length() == 0) {
        throw new IllegalArgumentException("Path must not be empty.");
    }
    return load(Uri.parse(path));
}

public RequestCreator load(@NonNull File file) {
    if (file == null) {
        return new RequestCreator(this, null, 0);
    }
    return load(Uri.fromFile(file));
}

public RequestCreator load(@DrawableRes int resourceId) {
    if (resourceId == 0) {
        throw new IllegalArgumentException("Resource ID must not be zero.");
    }
    return new RequestCreator(this, null, resourceId);
}

RequestCreator对象

//fetch()方式
Action action =
new FetchAction(picasso, request, memoryPolicy, 
networkPolicy, tag, key, callback);
picasso.submit(action);

//into()方式
Action action =
new ImageViewAction(picasso, target, request, 
memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
picasso.enqueueAndSubmit(action);

Picasso 类对应方法

void enqueueAndSubmit(Action action) {
    Object target = action.getTarget();
    if (target != null && targetToAction.get(target) != action) {
        // This will also check we are on the main thread.
        cancelExistingRequest(target);
        targetToAction.put(target, action);
    }
    submit(action);
}

void submit(Action action) {
    dispatcher.dispatchSubmit(action);
}

Dispatcher是如何进行消息分发和执行

//Dispatcher成员变量
final DispatcherThread dispatcherThread;//消息循环线程
final Context context;
final ExecutorService service;//执行线程池
final Downloader downloader;//下载器
final Map<String, BitmapHunter> hunterMap;
final Map<Object, Action> failedActions;
final Map<Object, Action> pausedActions;
final Set<Object> pausedTags;
final Handler handler;//消息处理者
final Handler mainThreadHandler;
final Cache cache;//内存缓存
final Stats stats;//统计快照
final List<BitmapHunter> batch;
final NetworkBroadcastReceiver receiver;//网络状况广播接受者
final boolean scansNetworkChanges;

//最重要的是开启了一个消息循环线程DispatcherThread
static class DispatcherThread extends HandlerThread {
    DispatcherThread() {
        super(Utils.THREAD_PREFIX 
        + DISPATCHER_THREAD_NAME, THREAD_PRIORITY_BACKGROUND);
    }
}
//DispatcherThread其实是一个HandlerThread,也就是一个带有Looper的线程。
this.handler = new DispatcherHandler(dispatcherThread.getLooper(), this);




参考文献
1.Picasso源码阅读
2.Android 图片加载框架Picasso基本使用和源码完全解析
3.Android开发之线程池使用总

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。