Fresco源碼解析:初始化過程(二)

本文承接Fresco源碼解析: 初始化過程(一)

從ImagePipelineConfig的構造函數開始,再貼一遍代碼

 private ImagePipelineConfig(Builder builder) {
    // We have to build experiments before the rest
    //目前處於實驗狀態的一些選項,變動很大,官方建議不要修改這些選項的默認值
    mImagePipelineExperiments = builder.mExperimentsBuilder.build();
    //bitmap內存緩存參數的提供者,以MemoryCacheParams類的形式封裝
    mBitmapMemoryCacheParamsSupplier = builder.mBitmapMemoryCacheParamsSupplier == null ?
            new DefaultBitmapMemoryCacheParamsSupplier((ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
            builder.mBitmapMemoryCacheParamsSupplier;
    //內存回收策略
    mBitmapMemoryCacheTrimStrategy = builder.mBitmapMemoryCacheTrimStrategy == null ? new BitmapMemoryCacheTrimStrategy() :
            builder.mBitmapMemoryCacheTrimStrategy;
   // bitmap的配置參數,Bitmap.Config默認使用ARGB_8888,相對於Glid更好內存
    mBitmapConfig = builder.mBitmapConfig == null ? Bitmap.Config.ARGB_8888 : builder.mBitmapConfig;
    //生成緩存key的工廠,如果不想使用默認的key生成方法,可以自定義這個factory
    mCacheKeyFactory = builder.mCacheKeyFactory == null ? DefaultCacheKeyFactory.getInstance() : builder.mCacheKeyFactory;
    mContext = Preconditions.checkNotNull(builder.mContext);
    //文件緩存的工廠
    mFileCacheFactory = builder.mFileCacheFactory == null ? new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory()) :
        builder.mFileCacheFactory;
    mDownsampleEnabled = builder.mDownsampleEnabled;
    //未解碼的內存緩存參數 
    mEncodedMemoryCacheParamsSupplier = builder.mEncodedMemoryCacheParamsSupplier == null ? new DefaultEncodedMemoryCacheParamsSupplier() :
            builder.mEncodedMemoryCacheParamsSupplier;
            //圖片緩存統計跟蹤工具
    mImageCacheStatsTracker = builder.mImageCacheStatsTracker == null ? NoOpImageCacheStatsTracker.getInstance() : builder.mImageCacheStatsTracker;
    //圖片解碼工具
    mImageDecoder = builder.mImageDecoder;
    //是否開啓預加載的開關提供者,默認是開啓
    mIsPrefetchEnabledSupplier = builder.mIsPrefetchEnabledSupplier == null ?
            new Supplier<Boolean>() {
              @Override
              public Boolean get() {
                return true;
              }
            } :
            builder.mIsPrefetchEnabledSupplier;
//主硬盤緩存的配置參數
mMainDiskCacheConfig = builder.mMainDiskCacheConfig == null ? getDefaultMainDiskCacheConfig(builder.mContext) :
            builder.mMainDiskCacheConfig;
     //那些需要監聽系統內存變化的對象,就需要添加到這個對象中
    mMemoryTrimmableRegistry = builder.mMemoryTrimmableRegistry == null ? NoOpMemoryTrimmableRegistry.getInstance() :
            builder.mMemoryTrimmableRegistry;
     //網絡數據獲取的工具,默認使用HttpUrlConnectionNetworkFetcher,也可以自己定義
    mNetworkFetcher = builder.mNetworkFetcher == null ?  new HttpUrlConnectionNetworkFetcher() : builder.mNetworkFetcher;
    //根據不同android版本生成不同的bitmap的工廠,主要是bitmap內存存儲位置,5.0以前存儲在ashmem,5.0以後存在java heap中,默認爲空
    mPlatformBitmapFactory = builder.mPlatformBitmapFactory;
    //生產各種池的工廠
    mPoolFactory = builder.mPoolFactory == null ? new PoolFactory(PoolConfig.newBuilder().build()) : builder.mPoolFactory;
    //漸進式加載的配置參數
    mProgressiveJpegConfig = builder.mProgressiveJpegConfig == null ? new SimpleProgressiveJpegConfig() :builder.mProgressiveJpegConfig;
    //監聽request過程中的各種事件
    mRequestListeners = builder.mRequestListeners == null ? new HashSet<RequestListener>() : builder.mRequestListeners;
    mResizeAndRotateEnabledForNetwork = builder.mResizeAndRotateEnabledForNetwork;
    //小圖硬盤緩存的配置參數,對應於mMainDiskCacheConfig 
    mSmallImageDiskCacheConfig = builder.mSmallImageDiskCacheConfig == null ? mMainDiskCacheConfig :builder.mSmallImageDiskCacheConfig;
    //圖片解碼器的配置參數
    mImageDecoderConfig = builder.mImageDecoderConfig;
    // Below this comment can't be built in alphabetical order, because of dependencies
   //允許訪問線程池的最大線程數
    int numCpuBoundThreads = mPoolFactory.getFlexByteArrayPoolMaxNumThreads();
    //線程池
    mExecutorSupplier = builder.mExecutorSupplier == null ? new DefaultExecutorSupplier(numCpuBoundThreads) : builder.mExecutorSupplier;
    // Here we manage the WebpBitmapFactory implementation if any
    //在不支持webp的android版本上(4.0開始支持簡單的webp,4.2.1後全面支持)支持解碼webp圖片的工廠,默認爲null
    WebpBitmapFactory webpBitmapFactory = mImagePipelineExperiments.getWebpBitmapFactory();
    if (webpBitmapFactory != null) {
      BitmapCreator bitmapCreator = new HoneycombBitmapCreator(getPoolFactory());
      setWebpBitmapFactory(webpBitmapFactory, mImagePipelineExperiments, bitmapCreator);
    } else {
      // We check using introspection only if the experiment is enabled
      if (mImagePipelineExperiments.isWebpSupportEnabled() &&
          WebpSupportStatus.sIsWebpSupportRequired) {
        webpBitmapFactory = WebpSupportStatus.loadWebpBitmapFactoryIfExists();
        if (webpBitmapFactory != null) {
          BitmapCreator bitmapCreator = new HoneycombBitmapCreator(getPoolFactory());
          setWebpBitmapFactory(webpBitmapFactory, mImagePipelineExperiments, bitmapCreator);
        }
      }
    }
  }
 //目前處於實驗狀態的一些選項,變動很大,官方建議不要修改這些選項的默認值
    mImagePipelineExperiments = builder.mExperimentsBuilder.build();

上面這行代碼主要構造了一個ImagePipelineExperiments對象,類介紹如下:

Encapsulates additional elements of the ImagePipelineConfig which are currently in an >experimental state.
These options may often change or disappear altogether and it is not recommended to change >their values from their defaults.

大致意思就是說這個類裏包含了一些正在處於實驗階段的ImagePipelineConfig 中的元素,這些元素經常在變或者消失,所以不建議去改變他們的默認值。我這裏也不再詳細的說明,有興趣可以看源碼或者官方文檔。

 //bitmap內存緩存參數的提供者,以MemoryCacheParams類的形式封裝
    mBitmapMemoryCacheParamsSupplier = builder.mBitmapMemoryCacheParamsSupplier == null ?
            new DefaultBitmapMemoryCacheParamsSupplier((ActivityManager) 

上面代碼是初始化bitmap內存緩存的參數提供者,默認使用DefaultBitmapMemoryCacheParamsSupplier,我們看下DefaultBitmapMemoryCacheParamsSupplier的代碼,主要看get()方法:

public class DefaultBitmapMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> {
  private static final int MAX_CACHE_ENTRIES = 256;
  private static final int MAX_EVICTION_QUEUE_SIZE = Integer.MAX_VALUE;
  private static final int MAX_EVICTION_QUEUE_ENTRIES = Integer.MAX_VALUE;
  private static final int MAX_CACHE_ENTRY_SIZE = Integer.MAX_VALUE;

  private final ActivityManager mActivityManager;

  public DefaultBitmapMemoryCacheParamsSupplier(ActivityManager activityManager) {
    mActivityManager = activityManager;
  }

  @Override
  public MemoryCacheParams get() {
    return new MemoryCacheParams(
        getMaxCacheSize(),
        MAX_CACHE_ENTRIES,
        MAX_EVICTION_QUEUE_SIZE,
        MAX_EVICTION_QUEUE_ENTRIES,
        MAX_CACHE_ENTRY_SIZE);
  }

  private int getMaxCacheSize() {
    final int maxMemory = Math.min(mActivityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE);
    if (maxMemory < 32 * ByteConstants.MB) {
      return 4 * ByteConstants.MB;
    } else if (maxMemory < 64 * ByteConstants.MB) {
      return 6 * ByteConstants.MB;
    } else {
      // We don't want to use more ashmem on Gingerbread for now, since it doesn't respond well to
      // native memory pressure (doesn't throw exceptions, crashes app, crashes phone)
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        return 8 * ByteConstants.MB;
      } else {
        return maxMemory / 4;
      }
    }
  }
} 

get()方法中新建了一個MemoryCacheParams對象,這個類很簡單,就是指定了緩存的一些參數,比如最多幾條數據等,源碼如下

public class MemoryCacheParams {

  public final int maxCacheSize;
  public final int maxCacheEntries;
  public final int maxEvictionQueueSize;
  public final int maxEvictionQueueEntries;
  public final int maxCacheEntrySize;

  /**
   * Pass arguments to control the cache's behavior in the constructor.
   *
   * @param maxCacheSize The maximum size of the cache, in bytes.
   * @param maxCacheEntries The maximum number of items that can live in the cache.
   * @param maxEvictionQueueSize The eviction queue is an area of memory that stores items ready
   *                             for eviction but have not yet been deleted. This is the maximum
   *                             size of that queue in bytes.
   * @param maxEvictionQueueEntries The maximum number of entries in the eviction queue.
   * @param maxCacheEntrySize The maximum size of a single cache entry.
   */
  public MemoryCacheParams(
      int maxCacheSize,
      int maxCacheEntries,
      int maxEvictionQueueSize,
      int maxEvictionQueueEntries,
      int maxCacheEntrySize) {
    this.maxCacheSize = maxCacheSize;
    this.maxCacheEntries = maxCacheEntries;
    this.maxEvictionQueueSize = maxEvictionQueueSize;
    this.maxEvictionQueueEntries = maxEvictionQueueEntries;
    this.maxCacheEntrySize = maxCacheEntrySize;
  }
}

我們看第一個參數也就是maxCacheSize,它指定了最大能緩存的內存總量,以byte爲單位。這個值的獲取是通過getMaxCacheSize()方法。邏輯如下:

通過使用getMemoryClass來確定當前應用可以開闢的最大heapsize,如果最大heapsize小於32M就設置爲4M,如果大於32M小於64M就設置爲6M。如果大於64M,則在HONEYCOMB(3.0)之前的機器上設置爲8M,之後的機器設置爲最大值除以4

關於爲什麼在3.0之前的機器上要做特殊處理,官網的解釋如下:

We don’t want to use more ashmem on Gingerbread for now, since it doesn’t respond well to
native memory pressure (doesn’t throw exceptions, crashes app, crashes phone)

也就是說在3.0以前的機器上,系統對ashmem的內存管理並不是做的很好,所以不想使用太多的ashmem內存。
其他幾項數值都是取Integer.MAX_VALUE

//bitmap內存緩存回收策略
mBitmapMemoryCacheTrimStrategy = builder.mBitmapMemoryCacheTrimStrategy == null ? new BitmapMemoryCacheTrimStrategy() :builder.mBitmapMemoryCacheTrimStrategy;

內存回收策略類,實現了CountingMemoryCache.CacheTrimStrategy接口,這個接口只有一個方法getTrimRatio(MemoryTrimType trimType),此方法的參數是MemoryTrimType類型,這個類是一個枚舉類型,裏面定義了一些內存回收的類型,每個類型有一個建議的內存回收比例,源代碼如下:

/**
 * Types of memory trim.
 *
 * <p>Each type of trim will provide a suggested trim ratio.
 *
 * <p>A {@link MemoryTrimmableRegistry} implementation sends out memory trim events with this type.
 */
public enum MemoryTrimType {

  /** The application is approaching the device-specific Java heap limit. */
  OnCloseToDalvikHeapLimit(0.5),

  /** The system as a whole is running out of memory, and this application is in the foreground. */
  OnSystemLowMemoryWhileAppInForeground(0.5),

  /** The system as a whole is running out of memory, and this application is in the background. */
  OnSystemLowMemoryWhileAppInBackground(1),

  /** This app is moving into the background, usually because the user navigated to another app. */
  OnAppBackgrounded(1);

  private double mSuggestedTrimRatio;

  private MemoryTrimType(double suggestedTrimRatio) {
    mSuggestedTrimRatio = suggestedTrimRatio;
  }

  /** Get the recommended percentage by which to trim the cache on receiving this event. */
  public double getSuggestedTrimRatio () {
    return mSuggestedTrimRatio;
  }
}

所以getTrimRatio方法就是根據不同的回收類型,返回不同的回收比例,CacheTrimStrategy的默認的實現類是BitmapMemoryCacheTrimStrategy,源代碼如下:

/**
 * CountingMemoryCache eviction strategy appropriate for bitmap caches.
 *
 * <p>If run on KitKat or below, then this TrimStrategy behaves exactly as
 * NativeMemoryCacheTrimStrategy. If run on Lollipop, then BitmapMemoryCacheTrimStrategy will trim
 * cache in one additional case: when OnCloseToDalvikHeapLimit trim type is received, cache's
 * eviction queue will be trimmed according to OnCloseToDalvikHeapLimit's suggested trim ratio.
 */
public class BitmapMemoryCacheTrimStrategy implements CountingMemoryCache.CacheTrimStrategy {
  private static final String TAG = "BitmapMemoryCacheTrimStrategy";

  @Override
  public double getTrimRatio(MemoryTrimType trimType) {
    switch (trimType) {
      case OnCloseToDalvikHeapLimit:
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          return MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio();
        } else {
          // On pre-lollipop versions we keep bitmaps on the native heap, so no need to trim here
          // as it wouldn't help Dalvik heap anyway.
          return 0;
        }
      case OnAppBackgrounded:
      case OnSystemLowMemoryWhileAppInForeground:
      case OnSystemLowMemoryWhileAppInBackground:
        return 1;
      default:
        FLog.wtf(TAG, "unknown trim type: %s", trimType);
        return 0;
    }
  }
}

這個類註釋似乎和代碼的實現有點不一樣。。。先留着回頭再看是否真的有問題

 //文件緩存的工廠
    mFileCacheFactory = builder.mFileCacheFactory == null ? new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory()) :
        builder.mFileCacheFactory;

文件緩存的工廠,實現了FileCacheFactory接口,這個接口只有一個get方法,用於返回一個FileCache實例,這個FileCache就是用來管理文件緩存。這裏的FileCacheFactory默認實現是DiskStorageCacheFactory,看名字就是硬盤緩存,如果有興趣也可以用別的途徑實現,database?它的構造函數需要一個實現了DiskStorageFactory接口的實例,DiskStorageFactory接口就是用來提供實現DiskStorage接口的實例的,DiskStorage接口描述如下:

Storage for files in the cache.
Responsible for maintaining state (count, size, watch file existence, reachability)

意思就是用來保存緩存的文件,並負責維護狀態,比如個數,大小,文件後綴,是否可達等。裏面提供了一些操作文件的方法,如圖DiskStorage的一些方法。其中有一個值得注意的方法是

  /**
   * Creates a temporary resource for writing content. Split from commit()
   * in order to allow concurrent writing of cache entries.
   * This entry will not be available to cache clients until
   * commit() is called passing in the resource returned
   * from this method.
   * @param resourceId id of the resource
   * @param debugInfo helper object for debugging
   * @return the Inserter object with methods to write data, commit or cancel the insertion
   * @exception IOException on errors during this operation
   */
 Inserter insert(String resourceId, Object debugInfo)throws IOException;

從方法描述可以看出,這個方法不是直接把緩存文件放進緩存,中間會有一個緩存文件,而用戶要通過操作方法返回的Inserter 接口來實現真正的commit。具體的實現可以參考DynamicDefaultDiskStorageFactory。

//未解碼的內存緩存參數提供器 
mEncodedMemoryCacheParamsSupplier = builder.mEncodedMemoryCacheParamsSupplier == null ? new DefaultEncodedMemoryCacheParamsSupplier() :builder.mEncodedMemoryCacheParamsSupplier;

圖片剛從網上下載之後是沒有被解碼的,Fresco對這部分的數據也會緩存在內存中,這個緩存的一些參數參數就由DefaultEncodedMemoryCacheParamsSupplier提供,我們可以看一下它的具體實現,到底提供了哪些參數。

/**
 * Supplies {@link MemoryCacheParams} for the encoded image memory cache
 */
public class DefaultEncodedMemoryCacheParamsSupplier implements Supplier<MemoryCacheParams> {

  // We want memory cache to be bound only by its memory consumption
  private static final int MAX_CACHE_ENTRIES = Integer.MAX_VALUE;
  private static final int MAX_EVICTION_QUEUE_ENTRIES = MAX_CACHE_ENTRIES;

  @Override
  public MemoryCacheParams get() {
    final int maxCacheSize = getMaxCacheSize();
    final int maxCacheEntrySize = maxCacheSize / 8;
    return new MemoryCacheParams(
        maxCacheSize,
        MAX_CACHE_ENTRIES,
        maxCacheSize,
        MAX_EVICTION_QUEUE_ENTRIES,
        maxCacheEntrySize);
  }

  private int getMaxCacheSize() {
    final int maxMemory = (int) Math.min(Runtime.getRuntime().maxMemory(), Integer.MAX_VALUE);
    if (maxMemory < 16 * ByteConstants.MB) {
      return 1 * ByteConstants.MB;
    } else if (maxMemory < 32 * ByteConstants.MB) {
      return 2 * ByteConstants.MB;
    } else {
      return 4 * ByteConstants.MB;
    }
  }
}

可以看到,整個結構和前面提到的DefaultBitmapMemoryCacheParamsSupplier是一樣的,都是實現了Supplier<MemoryCacheParams>接口,然後通過 MemoryCacheParams來封裝這些參數,所以提供的參數也是一樣的。

//圖片緩存統計跟蹤工具
mImageCacheStatsTracker = builder.mImageCacheStatsTracker == null ? NoOpImageCacheStatsTracker.getInstance() : builder.mImageCacheStatsTracker;

ImageCacheStatsTracker是一個接口,裏面定義了一些回調方法,當圖片緩存發生變化時(包括bitmap和EncodedImage)會回調這些方法,用戶可以重寫這些方法,默認的實現類NoOpImageCacheStatsTracker沒有重寫任何方法,這裏應該屬於接口的適配器設計模式,用戶可以通過繼承NoOpImageCacheStatsTracker類來重寫自己關心的回調方法,比如有新的bitmap圖片加入緩存了,會回調onBitmapCachePut()

//主硬盤緩存的配置參數
mMainDiskCacheConfig = builder.mMainDiskCacheConfig == null ? getDefaultMainDiskCacheConfig(builder.mContext) : builder.mMainDiskCacheConfig;
//小圖硬盤緩存的配置參數,對應於mMainDiskCacheConfig 
mSmallImageDiskCacheConfig = builder.mSmallImageDiskCacheConfig == null ? mMainDiskCacheConfig :builder.mSmallImageDiskCacheConfig;

其中的MainDiskCacheConfig就是一般圖片的緩存,平時的圖片都是緩存在這裏,而SmallImage是什麼呢?官網文檔有說明:

用一個還是兩個磁盤緩存?
如果要使用2個緩存,在配置image pipeline 時調用 setMainDiskCacheConfig 和 setSmallImageDiskCacheConfig 方法即可。
大部分的應用有一個磁盤緩存就夠了,但是在一些情況下,你可能需要兩個緩存。比如你也許想把小文件放在一個緩存中,大文件放在另外一個文件中,這樣小文件就不會因大文件的頻繁變動而被從緩存中移除。
至於什麼是小文件,這個由應用來區分,在創建image request, 設置 ImageType 即可:

ImageRequest request = ImageRequest.newBuilderWithSourceUri(uri)
    .setImageType(ImageType.SMALL)

如果你僅僅需要一個緩存,那麼不調用setSmallImageDiskCacheConfig即可。Image pipeline 默認會使用>同一個緩存,同時ImageType也會被忽略。

也就是說只有被設置爲ImageType.SMALL的圖片纔會存到SmallImageDiskCache,也纔會使用到mSmallImageDiskCacheConfig。那這個config到底配置了哪些東西呢,當然要看源碼了。在默認情況下使用的是getDefaultMainDiskCacheConfig()方法返回的實力,我們就看這個方法,源碼如下:

  private static DiskCacheConfig getDefaultMainDiskCacheConfig(final Context context) {
    return DiskCacheConfig.newBuilder(context).build();
  }

是一個建造者模式,我們直接進到build()方法:

    public DiskCacheConfig build() {
      Preconditions.checkState(
          mBaseDirectoryPathSupplier != null || mContext != null,
          "Either a non-null context or a base directory path or supplier must be provided.");
      if (mBaseDirectoryPathSupplier == null && mContext != null) {
        mBaseDirectoryPathSupplier = new Supplier<File>() {
          @Override
          public File get() {
            return mContext.getApplicationContext().getCacheDir();
          }
        };
      }
      return new DiskCacheConfig(this);
    }

邏輯很簡單,先檢查mBaseDirectoryPathSupplier和mContext是否有一個不爲空,只有要一個不爲空就繼續,然後如果 mBaseDirectoryPathSupplier爲null,就新建一個Supplier<File>實例,從變量名字看,這個supplier就是指定了緩存文件個根目錄,就是通過getCacheDir()返回的目錄,最後再返回一個DiskCacheConfig實例,我們看一下這個構造函數。

  private DiskCacheConfig(Builder builder) {
    mVersion = builder.mVersion;
    mBaseDirectoryName = Preconditions.checkNotNull(builder.mBaseDirectoryName);
    mBaseDirectoryPathSupplier = Preconditions.checkNotNull(builder.mBaseDirectoryPathSupplier);
    mDefaultSizeLimit = builder.mMaxCacheSize;
    mLowDiskSpaceSizeLimit = builder.mMaxCacheSizeOnLowDiskSpace;
    mMinimumSizeLimit = builder.mMaxCacheSizeOnVeryLowDiskSpace;
    mEntryEvictionComparatorSupplier =  Preconditions.checkNotNull(builder.mEntryEvictionComparatorSupplier);
    mCacheErrorLogger = builder.mCacheErrorLogger == null ? NoOpCacheErrorLogger.getInstance() : builder.mCacheErrorLogger;
    mCacheEventListener = builder.mCacheEventListener == null ? NoOpCacheEventListener.getInstance() : builder.mCacheEventListener;
    mDiskTrimmableRegistry = builder.mDiskTrimmableRegistry == null ? NoOpDiskTrimmableRegistry.getInstance() :builder.mDiskTrimmableRegistry;
    mContext = builder.mContext;
    mIndexPopulateAtStartupEnabled = builder.mIndexPopulateAtStartupEnabled;
  }

第1行指定了config的版本,第2行指定了文件緩存的根目錄文件名,默認是ImagePipelineConfigFactory.IMAGE_PIPELINE_CACHE_DIR = "imagepipeline_cache"

下面這行就是之前在build方法中指定的緩存目錄路徑
mBaseDirectoryPathSupplier =Preconditions.checkNotNull(builder.mBaseDirectoryPathSupplier);
所以默認的緩存目錄就是data/data/xxx.xxx.xx/cache/imagepipeline_cache。
mDefaultSizeLimit = builder.mMaxCacheSize;這行指定了默認最大的緩存大小,爲**40M**。
mLowDiskSpaceSizeLimit = builder.mMaxCacheSizeOnLowDiskSpace;指定了在硬盤存儲偏小的情況下,緩存的最大值。
mMinimumSizeLimit = builder.mMaxCacheSizeOnVeryLowDiskSpace;這個值用於計算在設備磁盤緩存特別特別低的時候,對硬盤緩存進行回收時的比例。

mEntryEvictionComparatorSupplier =  Preconditions.checkNotNull(builder.mEntryEvictionComparatorSupplier);

指定那些需要被移除的緩存條目的排序器,默認實現是DefaultEntryEvictionComparatorSupplier,是按訪問時間來排序,將最舊的移除。

mCacheErrorLogger = builder.mCacheErrorLogger == null ? NoOpCacheErrorLogger.getInstance() : builder.mCacheErrorLogger;

各種cache error的處理類,默認啥都沒做。

mCacheEventListener = builder.mCacheEventListener == null ? NoOpCacheEventListener.getInstance() : builder.mCacheEventListener;

各種緩存事件的處理類,默認啥都不做。

NoOpDiskTrimmableRegistry.getInstance():builder.mDiskTrimmableRegistry;    

這個類是用來管理那些實現了DiskTrimmable藉口的類,主要是當系統的硬盤空間發生變化的時候通知這些類

mIndexPopulateAtStartupEnabled = builder.mIndexPopulateAtStartupEnabled

對這個變量的作用還不是很清楚,先放着

以上就是DiskCacheConfig裏面配置的一些項目

 mNetworkFetcher = builder.mNetworkFetcher == null ? new HttpUrlConnectionNetworkFetcher() : builder.mNetworkFetcher;

網絡抓取的實現類,也就是真正從網上下載數據的地方,默認使用HttpUrlConnectionNetworkFetcher。

//生產各種池的工廠
mPoolFactory = builder.mPoolFactory == null ? new PoolFactory(PoolConfig.newBuilder().build()) : builder.mPoolFactory;

PoolFactory提供各種內存對象的池,比如bitmapPool,FlexByteArrayPool,NativeMemoryChunkPool等,這些pool在網絡抓取,圖片緩存中都會用到,這裏我們簡單看一下Fresco中的Pool實現原理,以BitmapPool爲例:

public class BitmapPool extends BasePool<Bitmap>
public abstract class BasePool<V> implements Pool<V> 

它繼承了BasePool,BasePool是一個抽象類,實現了Pool<V>接口,

public interface Pool<V> extends ResourceReleaser<V>, MemoryTrimmable

這個Pool接口又繼承了ResourceReleaser和MemoryTrimmable兩個接口,前者用於釋放資源,後者用於在內存不足的情況下回收內存,Pool接口本身有get(int size)release(V value)兩個方法。前者是用於從池中獲取指定大小的內容,如果不存在就開闢,後者用於向池釋放內容,如果池覺得這個內容還可以重用就先放在池裏,否則就釋放掉。具體的實現可以參考BitmapPool

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章