设计
Picasso 加载图片的流程
Picasso.get().load("").into(imageView);
Picasso.get()
创建一个 Picasso 单例,内部使用了建造者模式,单例模式和建造者模式。
load 方法返回一个 RequestCreator。
into 方法中中创建一个 request,request 作为创建 action 的参数之一,再 picasso.enqueueAndSubmit(action);
。
picasso submit 这个 action。
dispatcher.dispatchSubmit action,dispatcher 中的 handler 发送一个 message:
void dispatchSubmit(Action action) {
handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action));
}
dispatcher 内部有个 static 的 DispatcherHandler 类。收到 REQUEST_SUBMIT 类型的 message 会,dispatcher.performSubmit 。
尝试从 dispatcher 的 hunterMap 中根据 action 的 key 获取 BitmapHunter,将 hunter attach action。
上一步没获取到 hunter 时,dispatcher forRequest 创建 hunter,创建时将创建 picasso 时设置的 requestHander 设给 hunter:
static BitmapHunter forRequest(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats,
Action action) {
Request request = action.getRequest();
List<RequestHandler> requestHandlers = picasso.getRequestHandlers();
// Index-based loop to avoid allocating an iterator.
//noinspection ForLoopReplaceableByForEach
for (int i = 0, count = requestHandlers.size(); i < count; i++) {
RequestHandler requestHandler = requestHandlers.get(i);
if (requestHandler.canHandleRequest(request)) {
return new BitmapHunter(picasso, dispatcher, cache, stats, action, requestHandler);
}
}
return new BitmapHunter(picasso, dispatcher, cache, stats, action, ERRORING_HANDLER);
}
再:
hunter.future = service.submit(hunter);
BitmapHunter 实现了 Runnable,run 方法中 hunt 方法,从内存缓存中读,
读不到 requestHandler.load ,返回 RequestHandler.Result,
decodeStream
stats.dispatchBitmapDecoded
hunt 方法执行完返回 Bitmap,
result = hunt();
if (result == null) {
dispatcher.dispatchFailed(this);
} else {
dispatcher.dispatchComplete(this);
}
void dispatchComplete(BitmapHunter hunter) {
handler.sendMessage(handler.obtainMessage(HUNTER_COMPLETE, hunter));
}
case HUNTER_COMPLETE: {
BitmapHunter hunter = (BitmapHunter) msg.obj;
dispatcher.performComplete(hunter);
break;
}
写入内存缓存,再 dispatcher batch(),
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.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);
}
}
200 ms 后发送 HUNTER_DELAY_NEXT_BATCH message,
void performBatchComplete() {
List<BitmapHunter> copy = new ArrayList<>(batch);
batch.clear();
mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
logBatch(copy);
}
mainThreadHandler 是 picasso 中的 HANDLER,
complete
action.complete(result, from);
ImageViewAction
@Override public void complete(Bitmap result, Picasso.LoadedFrom from) {
if (result == null) {
throw new AssertionError(
String.format("Attempted to complete action with no result!\n%s", this));
}
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();
}
}
/**
* Create or update the drawable on the target {@link ImageView} to display the supplied bitmap
* image.
*/
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);
}