一、Picasso源码解析
(1)get():一个单例模式,为了保证线程安全,使用的是双重校验锁。创建的过程中又使用了Builder模式,实现链式调用。
public static Picasso get() {
if (singleton == null) {
synchronized (Picasso.class) {
if (singleton == null) {
if (PicassoProvider.context == null) {
throw new IllegalStateException("context == null");
}
singleton = new Builder(PicassoProvider.context).build();
}
}
}
return singleton;
}
//Picasso是针对应用级别的使用,不会是随着Activity或是Fragment的生命周期而产生变化,只有当前的应用退出或是销毁时Picasso才会停止它的行为。
public Builder(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("Context must not be null.");
}
this.context = context.getApplicationContext();
}
//初始化并返回Picasso实例对象
public Picasso build() {
Context context = this.context;
//downloader下载器
if (downloader == null) {
downloader = new OkHttp3Downloader(context);
}
//LruCache缓存
if (cache == null) {
cache = new LruCache(context);
}
//PicassoExecutorService线程池
if (service == null) {
service = new PicassoExecutorService();
}
//请求的前置处理,在请求发出去之前执行,类似于拦截器
if (transformer == null) {
transformer = RequestTransformer.IDENTITY;
}
//Stats图片的状态
Stats stats = new Stats(cache);
//调度器,分发任务
Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);
return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
}
}
- OkHttp3Downloader(context)下载器
public OkHttp3Downloader(final Context context) {
this(Utils.createDefaultCacheDir(context));
}
public OkHttp3Downloader(final File cacheDir) {
this(cacheDir, Utils.calculateDiskCacheSize(cacheDir));
}
public OkHttp3Downloader(final Context context, final long maxSize) {
this(Utils.createDefaultCacheDir(context), maxSize);
}
//缓存目录,缓存大小限制
public OkHttp3Downloader(final File cacheDir, final long maxSize) {
this(new OkHttpClient.Builder().cache(new Cache(cacheDir, maxSize)).build());
sharedClient = false;
}
//设置OkHttpClient与缓存文件
public OkHttp3Downloader(OkHttpClient client) {
this.client = client;
this.cache = client.cache();
}
- LruCache(context)缓存
public LruCache(@NonNull Context context) {
this(Utils.calculateMemoryCacheSize(context));
}
public LruCache(int maxByteCount) {
cache = new android.util.LruCache<String, LruCache.BitmapAndSize>(maxByteCount) {
@Override protected int sizeOf(String key, BitmapAndSize value) {
return value.byteCount;
}
};
}
//采用的LinkedHashMap,来保存缓存图片
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}
- PicassoExecutorService()线程池
- 重用线程池中的线程, 避免因为线程的创建和销毁所带来的性能开销.
- 有效控制线程池中的最大并发数,避免大量线程之间因为相互抢占系统资源而导致的阻塞现象.
- 能够对线程进行简单的管理,可提供定时执行和按照指定时间间隔循环执行等功能
PicassoExecutorService() {
super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS,
new PriorityBlockingQueue<Runnable>(), new Utils.PicassoThreadFactory());
}
//corePoolSize: 线程池的核心线程数
//maximumPoolSize: 最大的线程数
//keepAliveTime: 超时的时间
//unit:超时时间的时间单位.
//workQueue:线程池的任务队列
//threadFactory: 线程工厂
//handler: 任务无法执行时,回调handler的rejectedExecution方法来通知调用者
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
- Stats(cache)图片的状态
//状态信息
Stats(Cache cache) {
this.cache = cache;
this.statsThread = new HandlerThread(STATS_THREAD_NAME, THREAD_PRIORITY_BACKGROUND);
this.statsThread.start();
Utils.flushStackLocalLeaks(statsThread.getLooper());
this.handler = new StatsHandler(statsThread.getLooper(), this);
}
- Dispatcher调度器控制线程的加载和取消、网络监听、消息处理等。
Dispatcher(Context context, ExecutorService service, Handler mainThreadHandler,
Downloader downloader, Cache cache, Stats stats) {
this.dispatcherThread = new DispatcherThread();//DispatcherThread继承HandlerThread
this.dispatcherThread.start();
Utils.flushStackLocalLeaks(dispatcherThread.getLooper());
this.context = context;
this.service = service;
this.hunterMap = new LinkedHashMap<>();
this.failedActions = new WeakHashMap<>();
this.pausedActions = new WeakHashMap<>();
this.pausedTags = new LinkedHashSet<>();
this.handler = new DispatcherHandler(dispatcherThread.getLooper(), this);//在子线程运行的handler,自定义消息分发
this.downloader = downloader;
this.mainThreadHandler = mainThreadHandler;
this.cache = cache;
this.stats = stats;
this.batch = new ArrayList<>(4);
this.airplaneMode = Utils.isAirplaneModeOn(this.context);
this.scansNetworkChanges = hasPermission(context, Manifest.permission.ACCESS_NETWORK_STATE);
this.receiver = new NetworkBroadcastReceiver(this);
receiver.register();
}
- DispatcherHandler.handleMessage
//消息并没有被直接进行处理而是转移到了dispatcher中,在dispatcher中进行相应的处理
private static class DispatcherHandler extends Handler {
//code..
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case REQUEST_SUBMIT: {
Action action = (Action) msg.obj;
dispatcher.performSubmit(action);
break;
}
//code...
case HUNTER_COMPLETE: {
BitmapHunter hunter = (BitmapHunter) msg.obj;
dispatcher.performComplete(hunter);
break;
}
//code...
case HUNTER_DELAY_NEXT_BATCH: {
dispatcher.performBatchComplete();
break;
}
//code...
}
}
}
void performSubmit(Action action) {
performSubmit(action, true);
}
void performSubmit(Action action, boolean dismissFailed) {
if (pausedTags.contains(action.getTag())) {
pausedActions.put(action.getTarget(), action);
return;
}
//查看是否有对应url的缓存的hunter
BitmapHunter hunter = hunterMap.get(action.getKey());
if (hunter != null) {
hunter.attach(action);
return;
}
if (service.isShutdown()) {
if (action.getPicasso().loggingEnabled) {
log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down");
}
return;
}
hunter = forRequest(action.getPicasso(), this, cache, stats, action);
//提交任务到线程池
hunter.future = service.submit(hunter);
//将runnable缓存在map集合中
hunterMap.put(action.getKey(), hunter);
if (dismissFailed) {
failedActions.remove(action.getTarget());
}
}
- 创建BitmapHunter执行run方法
@Override
public void run() {
try {
updateThreadName(data);
//获取bitmap图片
result = hunt();
//判断bitmap是否为空
if (result == null) {
//失败回调
dispatcher.dispatchFailed(this);
} else {
//失败回调
dispatcher.dispatchComplete(this);
}
}
//code...
}
- 成功回调方法dispatchComplete
void dispatchComplete(BitmapHunter hunter) {
handler.sendMessage(handler.obtainMessage(HUNTER_COMPLETE, hunter));
}
//通过handleMessage调用
void performComplete(BitmapHunter hunter) {
//将图片添加到临时缓存
if (shouldWriteToMemoryCache(hunter.getMemoryPolicy())) {
cache.set(hunter.getKey(), hunter.getResult());
}
//删除下载任务
hunterMap.remove(hunter.getKey());
batch(hunter);
}
private void batch(BitmapHunter hunter) {
if (hunter.isCancelled()) {
return;
}
if (hunter.result != null) {
hunter.result.prepareToDraw();
}
batch.add(hunter);
if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH)) {
//发送延迟任务到handler
handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);
}
}
- 通过handleMessage接收延迟任务调用performBatchComplete()
void performBatchComplete() {
List<BitmapHunter> copy = new ArrayList<>(batch);
batch.clear();
//发送任务到Picasso的HANDLER主线程的handler中
mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
logBatch(copy);
}
- 查看Picasso.HANDLER中的handleMessage方法
static final Handler HANDLER = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case HUNTER_BATCH_COMPLETE: {
@SuppressWarnings("unchecked")
//获取图片
List<BitmapHunter> batch = (List<BitmapHunter>) msg.obj;
for (int i = 0, n = batch.size(); i < n; i++) {
BitmapHunter hunter = batch.get(i);
//通过调用complete最终调用ImageViewAction中complete方法
hunter.picasso.complete(hunter);
}
break;
}
//code...
}
}
};
//ImageViewAction.java
@Override
public void complete(Bitmap result, Picasso.LoadedFrom from) {
//code...
ImageView target = this.target.get();
if (target == null) {
return;
}
Context context = picasso.context;
boolean indicatorsEnabled = picasso.indicatorsEnabled;
PicassoDrawable.setBitmap(target, context, result, from, noFade, indicatorsEnabled);
if (callback != null) {
callback.onSuccess();
}
}
//PicassoDrawable.java
static void setBitmap(ImageView target, Context context, Bitmap bitmap,
Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) {
Drawable placeholder = target.getDrawable();
if (placeholder instanceof Animatable) {
((Animatable) placeholder).stop();
}
PicassoDrawable drawable =
new PicassoDrawable(context, bitmap, placeholder, loadedFrom, noFade, debugging);
target.setImageDrawable(drawable);
}
(2)load(imageUrl):加载url,创建并返回一个图片下载请求的构建器RequestCreator
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(@Nullable Uri uri) {
return new RequestCreator(this, uri, 0);
}
//RequestCreator.java
//请求构建器,用来存储该图片加载任务的一切信息
RequestCreator(Picasso picasso, Uri uri, int resourceId) {
if (picasso.shutdown) {
throw new IllegalStateException(
"Picasso instance already shut down. Cannot submit new requests.");
}
this.picasso = picasso;
this.data = new Request.Builder(uri, resourceId, picasso.defaultBitmapConfig);
}
(3)into(imageView):请求图片并返回
public void into(ImageView target) {
into(target, null);
}
public void into(ImageView target, Callback callback) {
long started = System.nanoTime();
//线程检查
checkMain();
if (target == null) {
throw new IllegalArgumentException("Target must not be null.");
}
if (!data.hasImage()) {
picasso.cancelRequest(target);
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
return;
}
if (deferred) {
if (data.hasSize()) {
throw new IllegalStateException("Fit cannot be used with resize.");
}
int width = target.getWidth();
int height = target.getHeight();
if (width == 0 || height == 0) {
//设置默认图
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
picasso.defer(target, new DeferredRequestCreator(this, target, callback));
return;
}
data.resize(width, height);
}
//Request的拦截器
Request request = createRequest(started);
//根据请求的URL,图片的处理等参数创建一个字符串Key
String requestKey = createKey(request);
//缓存策略,是否应该从内存中读取
if (shouldReadFromMemoryCache(memoryPolicy)) {
//内存的快速检查
Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);
if (bitmap != null) {
//如果缓存中已存在则取消请求并直接设置给ImageView
picasso.cancelRequest(target);
setBitmap(target, picasso.context, bitmap, MEMORY, noFade, picasso.indicatorsEnabled);
if (picasso.loggingEnabled) {
log(OWNER_MAIN, VERB_COMPLETED, request.plainId(), "from " + MEMORY);
}
if (callback != null) {
callback.onSuccess();
}
return;
}
}
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}
//创建ImageViewAction对象
Action action =
new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
errorDrawable, requestKey, tag, callback, noFade);
//提交请求
picasso.enqueueAndSubmit(action);
}