从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