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开发之线程池使用总