Picasso構(gòu)建過程

Picasso的構(gòu)建過程如下:

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
Picasso需要的默認(rèn)下載器。

try {
      Class.forName("com.squareup.okhttp.OkHttpClient");
      return OkHttpLoaderCreator.create(context);
    } catch (ClassNotFoundException ignored) {
    }
return new UrlConnectionDownloader(context);

該下載器會(huì)首先查找是否有okHttpClient類,如果找到,則創(chuàng)建并進(jìn)行配置。OkHttpClient 的緩存在Disk上,緩存大小為整個(gè)磁盤空間的2%(通過statFs計(jì)算得到),緩存路徑在/data/data/packageName/cache/picasso-cache下。
如果沒有找到OkHttpClienet,則使用HttpURLConnection完成下載工作。在Android4.0以上(包括4.0),提供了HttpResponseCache來(lái)支持硬盤緩存的功能。緩存空間和緩存路徑不變。
如果有在項(xiàng)目中使用OkHttp,可以將自定義的OkHttpClient單例配置進(jìn)Downloader中(繼承Downloader,在它的load函數(shù)中使用定義好的okHttpClient),這樣將保證所有網(wǎng)絡(luò)請(qǐng)求使用同一套client。

LruCache
基于LRU(近期最少使用)算法的內(nèi)存緩存器。
默認(rèn)緩存大小為app內(nèi)存的1/7,大約15%。
內(nèi)部本質(zhì)上維持著一個(gè)LinkedHashMap來(lái)存儲(chǔ)Btimap,主要是針對(duì)Bitmap的set和get。
set的時(shí)候,會(huì)統(tǒng)計(jì)Bitmap的大小,從而更新緩存中Bitmap總的大小,在set工作的最后,判斷當(dāng)前Bitmap的總量是否超過設(shè)定的緩存大小,從而決定是否需要對(duì)緩存進(jìn)行清理。
如果需要進(jìn)行清理,選擇LinkedHashMap的優(yōu)勢(shì)就出現(xiàn)了,不斷從迭代器中按照存入的先后順序取出Bitmap進(jìn)行remove。
get的時(shí)候,即是從Map中取,在這個(gè)過程會(huì)統(tǒng)計(jì)擊中數(shù)(hitCount)和未擊中數(shù)(missCount)。
如果你想統(tǒng)計(jì)擊中率,可以主動(dòng)創(chuàng)建一個(gè)LruCache對(duì)象,在Picasso構(gòu)建的時(shí)候添加進(jìn)去,這時(shí),可以取出hitCount和missCount?;蛘咝枰玫疆?dāng)前緩存大小,或者需要清空緩存,同樣需要這樣做。

PicassoExecutorService
查找Bitmap的線程池。
阻塞隊(duì)列使用PriorityBlockingQueue,同時(shí)根據(jù)網(wǎng)絡(luò)情況,會(huì)對(duì)線程池中的線程數(shù)進(jìn)行調(diào)整。如果無(wú)法感知到網(wǎng)絡(luò)情況,默認(rèn)線程數(shù)為3,有wifi情況為4,4g情況為3,3g情況為2,2g情況為1。
在該線程池中,執(zhí)行的實(shí)際上是通過BitmapHunter獲取Bitmap并對(duì)Bitmap進(jìn)行轉(zhuǎn)換的過程。
在BitmapHunter中核心代碼如下:

RequestHandler.Result result = requestHandler.load(data, networkPolicy);
bitmap = result.getBitmap();

上述的requestHandler是在Picasso實(shí)例化的時(shí)候在構(gòu)造函數(shù)中添加進(jìn)去的。Handler類型包括:

allRequestHandlers.add(new ContactsPhotoRequestHandler(context));
allRequestHandlers.add(new MediaStoreRequestHandler(context));
allRequestHandlers.add(new ContentStreamRequestHandler(context));
allRequestHandlers.add(new AssetRequestHandler(context));
allRequestHandlers.add(new FileRequestHandler(context));
allRequestHandlers.add(new NetworkRequestHandler(dispatcher.downloader, stats));

我們可以看到,對(duì)于需要網(wǎng)絡(luò)請(qǐng)求的得到Bitmap的過程是由NetworkRequestHandler來(lái)處理的。它會(huì)檢測(cè)該bitmap是否在磁盤上,還是需要進(jìn)行網(wǎng)絡(luò)訪問(本質(zhì)上,它把這件事交給了okHttpClient來(lái)處理)。
在BitmapHunter中獲取Bitmap之后,如果需要會(huì)對(duì)該Bitmap進(jìn)行轉(zhuǎn)換然后返回。

RequestTransformer
在request被提交之前使用該transformer來(lái)對(duì)request進(jìn)行修改。這是一個(gè)測(cè)試版特性,后續(xù)版本中可能不會(huì)兼容該特性。

Dispatcher
Dispatcher的主要作用,是處理各種動(dòng)作。

case REQUEST_SUBMIT: {
    Action action = (Action) msg.obj;
    dispatcher.performSubmit(action);
    break;
 }
 case REQUEST_CANCEL: {
    Action action = (Action) msg.obj;
    dispatcher.performCancel(action);
    break;
  }
case TAG_PAUSE: {
    Object tag = msg.obj;
    dispatcher.performPauseTag(tag);
    break;
}
case TAG_RESUME: {
    Object tag = msg.obj;
    dispatcher.performResumeTag(tag);
    break;
}
case HUNTER_COMPLETE: {
    BitmapHunter hunter = (BitmapHunter) msg.obj;
    dispatcher.performComplete(hunter);
    break;
}
case HUNTER_RETRY: {
    BitmapHunter hunter = (BitmapHunter) msg.obj;
    dispatcher.performRetry(hunter);
    break;
}
case HUNTER_DECODE_FAILED: {
    BitmapHunter hunter = (BitmapHunter) msg.obj;
    dispatcher.performError(hunter, false);
    break;
}
case HUNTER_DELAY_NEXT_BATCH: {
    dispatcher.performBatchComplete();
    break;
}
case NETWORK_STATE_CHANGE: {
    NetworkInfo info = (NetworkInfo) msg.obj;
    dispatcher.performNetworkStateChange(info);
    break;
}
case AIRPLANE_MODE_CHANGE: {
    dispatcher.performAirplaneModeChange(msg.arg1 == AIRPLANE_MODE_ON);
    break;
}
default:
    Picasso.HANDLER.post(new Runnable() {
        @Override public void run() {
          throw new AssertionError("Unknown handler message received: " + msg.what);
            }
    });
   

加載到ImageView過程
picasso.load(imageUrl).into(view);
load方法將返回一個(gè)RequestCreator對(duì)象。
在into的過程中,會(huì)為每個(gè)bitmap產(chǎn)生一個(gè)唯一的key,通過這個(gè)key來(lái)檢查該bitmap是或在內(nèi)存(LruCache)中,如果存在則直接返回(對(duì)磁盤緩存的檢查,是在BitmapHunte中進(jìn)行的,實(shí)際上由okHttpClient完成)。否則產(chǎn)生一個(gè)ImageViewAction提交給Dispatcher處理。
在Dispatcher中,核心代碼為:

//如果action被設(shè)置為pause tag
if (pausedTags.contains(action.getTag())) {
      ......
      return;
}
//如果action不是新的
BitmapHunter hunter = hunterMap.get(action.getKey());
    if (hunter != null) {
      hunter.attach(action);
      return;
    }
//如果線程池被關(guān)閉了
if (service.isShutdown()) {
      if (action.getPicasso().loggingEnabled) {
        log(OWNER_DISPATCHER, VERB_IGNORED, action.request.logId(), "because shut down");
      }
      return;
    }
//生成BitmapHunter
hunter = forRequest(action.getPicasso(), this, cache, stats, action);
//交給線程池,執(zhí)行
hunter.future = service.submit(hunter);
hunterMap.put(action.getKey(), hunter);
......   
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,192評(píng)論 25 708
  • Picasso,看的版本是v.2.5.2 使用方法,大概這么幾種加載資源的形式 還可以對(duì)圖片進(jìn)行一些操作:設(shè)置大小...
    Jinjins1129閱讀 416評(píng)論 0 3
  • 前一篇文章講了Picasso的詳細(xì)用法,Picasso 是一個(gè)強(qiáng)大的圖片加載緩存框架,一個(gè)非常優(yōu)秀的開源庫(kù),學(xué)習(xí)一...
    依然范特稀西閱讀 4,744評(píng)論 13 24
  • Picasso源碼完全解析(一)--概述 Picasso源碼完全解析(二)--Picasso實(shí)例的創(chuàng)建 Picas...
    三木青一閱讀 700評(píng)論 0 0
  • 二.哪些行為會(huì)加速衰老 1.情緒長(zhǎng)時(shí)間處于低落狀態(tài),壓力過大而自己無(wú)法調(diào)解,導(dǎo)致內(nèi)分泌紊亂。而內(nèi)分泌調(diào)節(jié)對(duì)抗衰老有...
    一只湯圓在南方閱讀 133評(píng)論 0 0

友情鏈接更多精彩內(nèi)容