從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)
意思就是用來保存緩存的文件,並負責維護狀態,比如個數,大小,文件後綴,是否可達等。裏面提供了一些操作文件的方法,如圖。其中有一個值得注意的方法是
/**
* 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