picasso的使用很是簡單。咱們只須要一行代碼就夠java
picasso.with(context).load(uri).into(imageView);算法
先看with方法緩存
public static Picasso with(Context context) { if (singleton == null) { synchronized (Picasso.class) { if (singleton == null) { singleton = new Builder(context).build(); } } } return singleton; }
這裏使用了單例模式,並且是雙重檢測鎖的方法。 另外還使用到了Builder模式,由於Picasso對象的建立很是複雜ide
咱們直接看build方法post
public Picasso build() { Context context = this.context; if (downloader == null) { downloader = Utils.createDefaultDownloader(context); } if (cache == null) { cache = new LruCache(context); } if (service == null) { service = new PicassoExecutorService(); } if (transformer == null) { transformer = RequestTransformer.IDENTITY; } 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); }
這裏先初始化Downloader,Cache(這裏使用的LRU算法),PicassoExecutorService(這是Picasso本身實現的線程池),Transformer(當請求被submit時能夠調用他去修改請求)。ui
接下來是Stats stats = new Stats(cache).this
能夠看下這裏類裏面的主要的成員變量url
final HandlerThread statsThread; final Cache cache; final Handler handler; long cacheHits; long cacheMisses; long totalDownloadSize; long totalOriginalBitmapSize; long totalTransformedBitmapSize; long averageDownloadSize; long averageOriginalBitmapSize; long averageTransformedBitmapSize; int downloadCount; int originalBitmapCount; int transformedBitmapCount;
主要爲了記錄一些緩存的命中次數,下載的文件大小,下載次數,原始文件大小等等信息,暫時先不看是幹什麼用的spa
這裏有一個Handler,是作什麼用的呢?好比Picasso請求一個以前已經請求過,如今已經被緩存過的圖片,這時候在訪問它就是命中了,這時候能夠調用 stats.dispatchCacheHit();線程
void dispatchCacheHit() { handler.sendEmptyMessage(CACHE_HIT); }
@Override public void handleMessage(final Message msg) { switch (msg.what) { case CACHE_HIT: stats.performCacheHit(); break; case CACHE_MISS: stats.performCacheMiss(); break; case BITMAP_DECODE_FINISHED: stats.performBitmapDecoded(msg.arg1); break; case BITMAP_TRANSFORMED_FINISHED: stats.performBitmapTransformed(msg.arg1); break; case DOWNLOAD_FINISHED: stats.performDownloadFinished((Long) msg.obj); break; default: Picasso.HANDLER.post(new Runnable() { @Override public void run() { throw new AssertionError("Unhandled stats message." + msg.what); } }); } }
就執行了performCacheHit方法,即cacheHits++
這裏爲何繞了一個大彎子,picasso先是調用stats.dispatchCacheHit().該方法裏經過handler發送一個消息,而後接收到消息後,把cacheHits++。爲何不直接在dispatchCacheHit方法裏cacheHits++。好比像downloadCount,totalDownloadSize等成員變量就是直接++的。
build()裏還有一行Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);
Dispatcher是幹什麼的呢?這是一個分發器,全部的請求都在這裏分發。
最後new Picasso對象返回。
--------------------------------with()到底結束--------------------
public RequestCreator load(Uri uri) { return new RequestCreator(this, uri, 0); }
RequestCreator 是用來建立一個圖片下載請求的類
--------------------------into()-------------------------------------
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 = createRequest(started); String requestKey = createKey(request); if (shouldReadFromMemoryCache(memoryPolicy)) { Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); if (bitmap != null) { 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()); } Action action = new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId, errorDrawable, requestKey, tag, callback, noFade); picasso.enqueueAndSubmit(action); }
首先記錄下開始時間,而後檢查是否是主線程執行的。
if (!data.hasImage())是什麼意思呢?data是this.data = new Request.Builder(uri, resourceId, picasso.defaultBitmapConfig);
boolean hasImage() { return uri != null || resourceId != 0; }
因此這裏是返回true的,因此暫時判斷裏的內容沒有執行
if (deferred) {//deferred在這裏是默認值false,因此花括號裏的內容也沒有執行
Request request = createRequest(started); //這裏建立了請求,給請求惟一的id,url,而且能夠轉換request String requestKey = createKey(request); //給請求建立了一個key
if (shouldReadFromMemoryCache(memoryPolicy)) { 這裏默認是進去的 Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); 先根據requestKey到cache裏找 若是cache裏能找到,就取消請求,直接設置 if (callback != null) { callback.onSuccess(); } //若是咱們以前傳callback進來的話,在成功設置圖片後,還能夠回調這個方法 若是cache裏沒有找到的話,
if (setPlaceholder) {
setPlaceholder(target, getPlaceholderDrawable());
}//看有沒有設置一個加載時默認顯示的圖片
最重要的一行
Action action = new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId, errorDrawable, requestKey, tag, callback, noFade);
Action表明了一個具體的加載任務,裏面有complete和error方法,主要用於回調
U最後
picasso.enqueueAndSubmit(action);
void enqueueAndSubmit(Action action) { Object target = action.getTarget(); //這個target就是ImageView if (target != null && targetToAction.get(target) != action) { //若是這個image以前尚未請求過 // This will also check we are on the main thread. cancelExistingRequest(target); targetToAction.put(target, action); } submit(action); }
if裏的,若是請求已經存在,則取消請求。從新放進去一遍
最後提交
void submit(Action action) { dispatcher.dispatchSubmit(action); }
void dispatchSubmit(Action action) { handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action)); }
這時候這個Dispatcher就起到分發的做用。
Dispatcher裏的handleMessage方法裏的
case REQUEST_SUBMIT: { Action action = (Action) msg.obj; dispatcher.performSubmit(action); break; }
void performSubmit(Action action) { performSubmit(action, true); } void performSubmit(Action action, boolean dismissFailed) { if (pausedTags.contains(action.getTag())) { pausedActions.put(action.getTarget(), action); if (action.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_PAUSED, action.request.logId(), "because tag '" + action.getTag() + "' is paused"); } return; } 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); hunterMap.put(action.getKey(), hunter); if (dismissFailed) { failedActions.remove(action.getTarget()); } if (action.getPicasso().loggingEnabled) { log(OWNER_DISPATCHER, VERB_ENQUEUED, action.request.logId()); } }
注意這裏的,hunter是一個Runnable,負責具體的加載,把最後加載的結果經過dispatcher分發出去
if (result == null) { dispatcher.dispatchFailed(this); } else { dispatcher.dispatchComplete(this); }
這個是run方法裏的一小段代碼