Picasso 是 Square 公司的大作,叫「畢加索」还棱,意為加載圖片就像畫畫一樣载慈,是一門藝術(shù)。他的組成結(jié)構(gòu)也很分明 :任務(wù)分發(fā)珍手,對象處理办铡,圖片的加載,緩存等琳要。
Picasso結(jié)構(gòu)圖
picasso有著非常強大的功能寡具,下面是picasso的流程圖
優(yōu)雅的picasso的調(diào)用形式:
1 with():單例創(chuàng)建picasso對象,實力化的默認的dowmloder焙蹭,LruCache晒杈,PicassoExecutorService,RequestTransformer孔厉,以及分發(fā)器Dispatcher拯钻,其中dispatcher創(chuàng)建了子線程和對應(yīng)的handler.
picasso主線程自己也有handler這兩個不一樣帖努,流程是,Dispatcher,接受到圖片加載完畢以后的消息后粪般,回調(diào)給picasso內(nèi)主handler提示圖片加載完畢
2 .load(imageUrl):返回RequestCreator的實例拼余。
public RequestCreator load(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));
}
內(nèi)部又創(chuàng)建了 Request.Builder
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);創(chuàng)建了ImageViewAction,并將action提交給diapatecher,
performSubmit()方法中實例了BitmapHunter(runnable)并提交到線程池中亩歹,
bitmaphunter的run方法:
@Override public void run() {
try {
updateThreadName(data);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_EXECUTING, getLogIdsForHunter(this));
}
result = hunt();
if (result == null) {
dispatcher.dispatchFailed(this);
} else {
dispatcher.dispatchComplete(this);
}
hunt內(nèi)部:通過 requestHandler.load()方法拿到bitmap
Bitmap hunt() throws IOException {
Bitmap bitmap = null;
if (shouldReadFromMemoryCache(memoryPolicy)) {
bitmap = cache.get(key);
if (bitmap != null) {
stats.dispatchCacheHit();
loadedFrom = MEMORY;
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED, data.logId(), "from cache");
}
return bitmap;
}
}
data.networkPolicy = retryCount == 0 ? NetworkPolicy.OFFLINE.index : networkPolicy;
RequestHandler.Result result = requestHandler.load(data, networkPolicy);
if (result != null) {
loadedFrom = result.getLoadedFrom();
exifRotation = result.getExifOrientation();
bitmap = result.getBitmap();
// If there was no Bitmap then we need to decode it from the stream.
if (bitmap == null) {
InputStream is = result.getStream();
try {
bitmap = decodeStream(is, data);
} finally {
Utils.closeQuietly(is);
}
}
}
if (bitmap != null) {
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_DECODED, data.logId());
}
stats.dispatchBitmapDecoded(bitmap);
if (data.needsTransformation() || exifRotation != 0) {
synchronized (DECODE_LOCK) {
if (data.needsMatrixTransform() || exifRotation != 0) {
bitmap = transformResult(data, bitmap, exifRotation);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId());
}
}
if (data.hasCustomTransformations()) {
bitmap = applyCustomTransformations(data.transformations, bitmap);
if (picasso.loggingEnabled) {
log(OWNER_HUNTER, VERB_TRANSFORMED, data.logId(), "from custom transformations");
}
}
}
if (bitmap != null) {
stats.dispatchBitmapTransformed(bitmap);
}
}
}
return bitmap;
}
拿到bitmap之后回調(diào)到diapatcher中
dispatcher中List<BitmapHunter>回調(diào)到Picasso主線程的handler中
void performBatchComplete() {
List<BitmapHunter> copy = new ArrayList<BitmapHunter>(batch);
batch.clear();
mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy));
logBatch(copy);
}
主線程handler的方法
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;
//noinspection ForLoopReplaceableByForEach
for (int i = 0, n = batch.size(); i < n; i++) {
BitmapHunter hunter = batch.get(i);
hunter.picasso.complete(hunter);
}
break;
}
deliverAction方法中的 action.complete(result, from)實現(xiàn)了為ImageView賦值的操作
private void deliverAction(Bitmap result, LoadedFrom from, Action action) {
if (action.isCancelled()) {
return;
}
if (!action.willReplay()) {
targetToAction.remove(action.getTarget());
}
if (result != null) {
if (from == null) {
throw new AssertionError("LoadedFrom cannot be null.");
}
action.complete(result, from);
if (loggingEnabled) {
log(OWNER_MAIN, VERB_COMPLETED, action.request.logId(), "from " + from);
}
} else {
action.error();
if (loggingEnabled) {
log(OWNER_MAIN, VERB_ERRORED, action.request.logId());
}
}
}
上述流程的圖