Picasso-源碼解析(二)

####前言 前面一篇文章簡單的介紹了Picasso的使用,已經整個源碼調用的流程,過了一遍。可是其中還有不少的細節咱們並無去涉及到。今天在昨天的基礎之上再進行深刻。java

Picasso對象

前面一篇文章咱們是從Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(ivTest)慢慢深刻的,這裏咱們也要找個能夠深刻的對象,就是最重要的Picasso對象。api

由於咱們在使用的時候就是直接Picasso.get().***這樣去調用的,因此說咱們先了解下Picasso全部的api,對整個框架的理解,以及對Picasso更有效率的使用。緩存

####public方法bash

image.png

咱們的as很強大,直接左側欄查看當前類的公用方法.網絡

這裏就把方法一個個介紹下。便於你們理解。app

  1. areIndicatorsEnabled(),setIndicatorsEnabled()
@SuppressWarnings("UnusedDeclaration") public void setIndicatorsEnabled(boolean enabled) {
    indicatorsEnabled = enabled;
  }
  @SuppressWarnings("UnusedDeclaration") public boolean areIndicatorsEnabled() {
    return indicatorsEnabled;
  }
複製代碼

用來設置和獲取是否顯示當前加載圖片的方式,上一篇文章有使用過,就是顯示當前圖片是由三級緩存中的哪個加載的。框架

  1. cancelRequest 看名字就知道,是直接用來取消請求的。 這裏能夠深刻下。
public void cancelRequest(@NonNull ImageView view) {
    if (view == null) {
      throw new IllegalArgumentException("view cannot be null.");
    }
    cancelExistingRequest(view);
  }
void cancelExistingRequest(Object target) {
    checkMain();
    //前面在加載圖片的時候是會target-action以key-value的方式保存在targetToAction中,後面我會指出,在哪裏保存的。這裏直接經過target獲取到action,而後cancel
    Action action = targetToAction.remove(target);
    if (action != null) {
      action.cancel();
      dispatcher.dispatchCancel(action);
    }
    //這裏就比較有意思,由於第一篇文章咱們介紹過,若是是`ImageView`的話,極可能會使用fit方法去適配`ImageView`的寬高,就有使用到DeferredRequestCreator,因此這裏要移除
    if (target instanceof ImageView) {
      ImageView targetImageView = (ImageView) target;
      DeferredRequestCreator deferredRequestCreator =
          targetToDeferredRequestCreator.remove(targetImageView);
      if (deferredRequestCreator != null) {
        deferredRequestCreator.cancel();
      }
    }
  }

複製代碼
  1. cancelTag,pauseTag,resumeTag 這3個一塊兒說,這3個能夠說是批量操做符。能夠簡單的看一下。
Picasso.get().load("http://i.imgur.com/DvpvklR.png")
                .tag("test")
                .into(ivTest)
        Picasso.get()
                .load("http://i.imgur.com/DvpvklR.png")
                .tag("test")
                .into(ivTest2)
        Picasso.get().cancelTag("test")
複製代碼

能夠先tag標記下每一個請求,而後能夠批量處理。 分別是取消,暫停,恢復。ide

  1. setLoggingEnabled,isLoggingEnabled
public void setLoggingEnabled(boolean enabled) {
    loggingEnabled = enabled;
  }
  public boolean isLoggingEnabled() {
    return loggingEnabled;
  }
複製代碼

是否啓動日誌學習

  1. getSnapshot
@SuppressWarnings("UnusedDeclaration") public StatsSnapshot getSnapshot() {
    return stats.createSnapshot();
  }
複製代碼

獲取到Picasso的一個快照。ui

Picasso.get().snapshot.dump()
複製代碼

而後直接打印。

===============BEGIN PICASSO STATS ===============
    Memory Cache Stats
      Max Cache Size: 57521883
      Cache Size: 0
      Cache % Full: 0
      Cache Hits: 0
      Cache Misses: 0
    Network Stats
      Download Count: 0
      Total Download Size: 0
      Average Download Size: 0
    Bitmap Stats
      Total Bitmaps Decoded: 0
      Total Bitmap Size: 0
      Total Transformed Bitmaps: 0
      Total Transformed Bitmap Size: 0
      Average Bitmap Size: 0
      Average Transformed Bitmap Size: 0
===============END PICASSO STATS ===============
複製代碼

這個就灰常的方便了,直接看當前Picasso的使用狀態

  1. invalidate 由於Picasso使用了LruCache緩存到內存中,key-value與url-bitmap對應起來(實際上不是保存Bitmap,而是本身封裝了另一個類,可是裏面是有Bitmap的,這裏先不具體)。invalidate能夠移除緩存。
public void invalidate(@Nullable Uri uri) {
    if (uri != null) {
      cache.clearKeyUri(uri.toString());
    }
  }
複製代碼
  1. load 這個就不說了,上一篇文章介紹了不少了。

重要對象介紹

上面簡單的了Picasso對象,可是還有不少重要的對象。 咱們能夠從Picasso.Builder中去尋找,由於這裏面都是咱們能夠配置的對象。

public static class Builder {
    private final Context context;
    private Downloader downloader;
    private ExecutorService service;
    private Cache cache;
    private Listener listener;
    private RequestTransformer transformer;
    private List<RequestHandler> requestHandlers;
    private Bitmap.Config defaultBitmapConfig;

    private boolean indicatorsEnabled;
    private boolean loggingEnabled;
...
複製代碼

這麼多能夠配置的對象,ndicatorsEnabled,loggingEnabled,context先不說了。

咱們來先來簡單介紹下另外幾個。

  1. Downloader downloader 默認實現OkHttp3Downloader
    @NonNull @Override public Response load(@NonNull Request request) throws IOException {
    return client.newCall(request).execute();
    複製代碼

} 實際上是能夠本身複寫,使用本身的http框架 2. ExecutorService service 默認實現`PicassoExecutorService`java

//建立了一個線程池,默認都是3個核心線程,而後還有一個有優先級的阻塞隊列
 PicassoExecutorService() {
super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS,
    new PriorityBlockingQueue<Runnable>(), new Utils.PicassoThreadFactory());
複製代碼

} ``` 這裏其實還有一個比較有意思的方法

void adjustThreadCount(NetworkInfo info) {
    if (info == null || !info.isConnectedOrConnecting()) {
      setThreadCount(DEFAULT_THREAD_COUNT);
      return;
    }
    switch (info.getType()) {
      case ConnectivityManager.TYPE_WIFI:
      case ConnectivityManager.TYPE_WIMAX:
      case ConnectivityManager.TYPE_ETHERNET:
        setThreadCount(4);
        break;
      case ConnectivityManager.TYPE_MOBILE:
        switch (info.getSubtype()) {
          case TelephonyManager.NETWORK_TYPE_LTE:  // 4G
          case TelephonyManager.NETWORK_TYPE_HSPAP:
          case TelephonyManager.NETWORK_TYPE_EHRPD:
            setThreadCount(3);
            break;
          case TelephonyManager.NETWORK_TYPE_UMTS: // 3G
          case TelephonyManager.NETWORK_TYPE_CDMA:
          case TelephonyManager.NETWORK_TYPE_EVDO_0:
          case TelephonyManager.NETWORK_TYPE_EVDO_A:
          case TelephonyManager.NETWORK_TYPE_EVDO_B:
            setThreadCount(2);
            break;
          case TelephonyManager.NETWORK_TYPE_GPRS: // 2G
          case TelephonyManager.NETWORK_TYPE_EDGE:
            setThreadCount(1);
            break;
          default:
            setThreadCount(DEFAULT_THREAD_COUNT);
        }
        break;
      default:
        setThreadCount(DEFAULT_THREAD_COUNT);
    }
  }
複製代碼

就是會根據網絡的狀況使用不一樣的線程數。能夠學習下。 也能夠自定義 3. Cache cache 默認使用LruCache

public LruCache(@NonNull Context context) {
    this(Utils.calculateMemoryCacheSize(context));
  }

...
static int calculateMemoryCacheSize(Context context) {
    ActivityManager am = getService(context, ACTIVITY_SERVICE);
    boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0;
    int memoryClass = largeHeap ? am.getLargeMemoryClass() : am.getMemoryClass();
    // Target ~15% of the available heap.
    return (int) (1024L * 1024L * memoryClass / 7);
  }

複製代碼

這裏也頗有意思,根據當前的app所能使用的內存值獲取一個比較合適的緩存內存的最大值。本身能夠複寫調整。

  1. Listener listener 沒有默認值
public interface Listener {
  void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception);
}
複製代碼

很顯然是用來全局監聽圖片加載失敗的事件。 5. RequestTransformer transformer 默認

RequestTransformer IDENTITY = new RequestTransformer() {
      @Override public Request transformRequest(Request request) {
        return request;
      }
    };
複製代碼

其實就是一個request的全局的一個轉化。默認不轉化。 6. List requestHandlers 前面已經介紹過了默認有不少種requestHandlers,也能夠本身定義 7. Bitmap.Config defaultBitmapConfig 默認爲null 在requestHandler裏面的createBitmapOptions有使用到

static BitmapFactory.Options createBitmapOptions(Request data) {
    final boolean justBounds = data.hasSize();
    final boolean hasConfig = data.config != null;
    BitmapFactory.Options options = null;
    if (justBounds || hasConfig || data.purgeable) {
      options = new BitmapFactory.Options();
      options.inJustDecodeBounds = justBounds;
      options.inInputShareable = data.purgeable;
      options.inPurgeable = data.purgeable;
    //在這裏,若是有config,就配置下,若是沒有那麼就默認
      if (hasConfig) {
        options.inPreferredConfig = data.config;
      }
    }
    return options;
  }
複製代碼

image.png

一共這麼多選項,能夠選擇。

總結

Picasso用起來也挺爽的,後面有空學習下Glide和Fresco作下對比

相關文章
相關標籤/搜索