Fresco源代码分析 之一 默认初始化
Fresco被认为是现在最为好用的Android图片加载库,在之前的文章,有根据官方文档分析过Fresco的入门手册,但使用始终无法明白其具体是怎么样工作的,因为,我们还是要从源码上分析Fresco的工作原理。
Fresco的初始化
在一般情况下,我们是使用默认的ImagePipeline配置来初始化Fresco的,代码如下:
1
|
Fresco
.
initialize
(
this
)
;
|
而实际上,Fresco一共提供了两个初始化方法
1
2
3
4
5
6
7
8
9
10
11
12
|
/** Initializes Fresco with the default config. */
public
static
void
initialize
(
Context
context
)
{
// 初始化了ImagePipelineFactory的默认配置
ImagePipelineFactory
.
initialize
(
context
)
;
initializeDrawee
(
context
)
;
}
/** Initializes Fresco with the specified config. */
public
static
void
initialize
(
Context
context
,
ImagePipelineConfig
imagePipelineConfig
)
{
ImagePipelineFactory
.
initialize
(
imagePipelineConfig
)
;
initializeDrawee
(
context
)
;
}
|
可以看到,这两个初始化方法仅仅是初始化ImagePipeline的不同,接下来依次分析。
初始化ImagePipelineFactory
同样的,ImagePipelineFactory总共提供了两个初始化方法,代码分别如下:
1
2
3
4
5
6
7
8
|
/** Initializes {@link ImagePipelineFactory} with default config. */
public
static
void
initialize
(
Context
context
)
{
initialize
(
ImagePipelineConfig
.
newBuilder
(
context
)
.
build
(
)
)
;
}
/** Initializes {@link ImagePipelineFactory} with the specified config. */
public
static
void
initialize
(
ImagePipelineConfig
imagePipelineConfig
)
{
sInstance
=
new
ImagePipelineFactory
(
imagePipelineConfig
)
;
}
|
其中可以看到initialize(Context context)本质上也是调用initialize(ImagePipelineConfig)的方法,因此实际上也就是设置的ImagePipelineConfig的不同,而实际上,这个参数也是从Fresco的初始化Fresco.initialize(Context, ImagePipelineFactory)传入的。因此,我们从分析ImagePipelineConfig.newBuilder(context).build()开始。
ImagePipelineConfig初始化
ImagePipelineConfig.newBuilder(context)其实是构造了ImagePipelineConfig#Builder对象,build()方法则反悔了ImagePipelineConfig对象,其中设置的属性都有如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Nullable
private
final
AnimatedImageFactory
mAnimatedImageFactory
;
// 动画工厂
private
final
Bitmap
.
Config
mBitmapConfig
;
// Bitmap配置
private
final
Supplier
&
lt
;
MemoryCacheParams
&
gt
;
mBitmapMemoryCacheParamsSupplier
;
// 缓存Bitmap所对应的MemoryCacheParams的供应者
private
final
CacheKeyFactory
mCacheKeyFactory
;
// CacheKey工厂
private
final
Context
mContext
;
// Context上下文
private
final
boolean
mDownsampleEnabled
;
// 是否运行下载缩略图
private
final
boolean
mDecodeFileDescriptorEnabled
;
// 是否允许解码文件描述否
private
final
boolean
mDecodeMemoryFileEnabled
;
// 是否允许解码内存中的文件
private
final
Supplier
&
lt
;
MemoryCacheParams
&
gt
;
mEncodedMemoryCacheParamsSupplier
;
// 缓存未解码的图像所对应的MemoryCacheParams的供应者
private
final
ExecutorSupplier
mExecutorSupplier
;
// 线程池供应商
private
final
ImageCacheStatsTracker
mImageCacheStatsTracker
;
// 记录ImageCache各种状态的工具
@Nullable
private
final
ImageDecoder
mImageDecoder
;
// 图片解码工具类
private
final
Supplier
&
lt
;
Boolean
&
gt
;
mIsPrefetchEnabledSupplier
;
// 是否允许预取的供应商
private
final
DiskCacheConfig
mMainDiskCacheConfig
;
// 磁盘缓存配置
private
final
MemoryTrimmableRegistry
mMemoryTrimmableRegistry
;
// 监听内存状态
private
final
NetworkFetcher
mNetworkFetcher
;
// 内存
@Nullable
private
final
PlatformBitmapFactory
mPlatformBitmapFactory
;
// 不同版本对应的BitmapFactory
private
final
PoolFactory
mPoolFactory
;
// Pool的工厂
private
final
ProgressiveJpegConfig
mProgressiveJpegConfig
;
// 对于渐进式Jpeg的配置
private
final
Set
&
lt
;
RequestListener
&
gt
;
mRequestListeners
;
// Request的监听者
private
final
boolean
mResizeAndRotateEnabledForNetwork
;
// 是否允许网络请求的图片设置大小或是旋转
private
final
DiskCacheConfig
mSmallImageDiskCacheConfig
;
// 小图片的磁盘缓存配置
|
ImagePipelineConfig内部的构造方法对本身复杂的参数进行设置,具体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
private
ImagePipelineConfig
(
Builder
builder
)
{
// 动画工厂
mAnimatedImageFactory
=
builder
.
mAnimatedImageFactory
;
// Bitmap 内存缓存参数 Supplier
mBitmapMemoryCacheParamsSupplier
=
builder
.
mBitmapMemoryCacheParamsSupplier
==
null
?
new
DefaultBitmapMemoryCacheParamsSupplier
(
(
ActivityManager
)
builder
.
mContext
.
getSystemService
(
Context
.
ACTIVITY_SERVICE
)
)
:
builder
.
mBitmapMemoryCacheParamsSupplier
;
// 图片的默认格式为 ARGB_8888
mBitmapConfig
=
builder
.
mBitmapConfig
==
null
?
Bitmap
.
Config
.
ARGB_8888
:
builder
.
mBitmapConfig
;
mCacheKeyFactory
=
builder
.
mCacheKeyFactory
==
null
?
DefaultCacheKeyFactory
.
getInstance
(
)
:
builder
.
mCacheKeyFactory
;
mContext
=
Preconditions
.
checkNotNull
(
builder
.
mContext
)
;
mDecodeFileDescriptorEnabled
=
builder
.
mDownsampleEnabled
&
amp
;
&
amp
;
builder
.
mDecodeFileDescriptorEnabled
;
mDecodeMemoryFileEnabled
=
builder
.
mDecodeMemoryFileEnabled
;
mDownsampleEnabled
=
builder
.
mDownsampleEnabled
;
mEncodedMemoryCacheParamsSupplier
=
builder
.
mEncodedMemoryCacheParamsSupplier
==
null
?
new
DefaultEncodedMemoryCacheParamsSupplier
(
)
:
builder
.
mEncodedMemoryCacheParamsSupplier
;
// 默认不记录Cache的Stat
mImageCacheStatsTracker
=
builder
.
mImageCacheStatsTracker
==
null
?
NoOpImageCacheStatsTracker
.
getInstance
(
)
:
builder
.
mImageCacheStatsTracker
;
mImageDecoder
=
builder
.
mImageDecoder
;
mIsPrefetchEnabledSupplier
=
builder
.
mIsPrefetchEnabledSupplier
==
null
?
new
Supplier
&
lt
;
Boolean
&
gt
;
(
)
{
@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
;
// 默认的网络Fetcher:HttpURLConnection
mNetworkFetcher
=
builder
.
mNetworkFetcher
==
null
?
new
HttpUrlConnectionNetworkFetcher
(
)
:
builder
.
mNetworkFetcher
;
mPlatformBitmapFactory
=
builder
.
mPlatformBitmapFactory
;
mPoolFactory
=
builder
.
mPoolFactory
==
null
?
new
PoolFactory
(
PoolConfig
.
newBuilder
(
)
.
build
(
)
)
:
builder
.
mPoolFactory
;
mProgressiveJpegConfig
=
builder
.
mProgressiveJpegConfig
==
null
?
new
SimpleProgressiveJpegConfig
(
)
:
builder
.
mProgressiveJpegConfig
;
mRequestListeners
=
builder
.
mRequestListeners
==
null
?
new
HashSet
&
lt
;
RequestListener
&
gt
;
(
)
:
builder
.
mRequestListeners
;
mResizeAndRotateEnabledForNetwork
=
builder
.
mResizeAndRotateEnabledForNetwork
;
mSmallImageDiskCacheConfig
=
builder
.
mSmallImageDiskCacheConfig
==
null
?
mMainDiskCacheConfig
:
builder
.
mSmallImageDiskCacheConfig
;
// 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
;
}
|
实际上,对于ImagePipeline默认初始化的理解,就在于对这些参数设置的理解上,因此,接下来我们因此分析每一种配置的所表示的意义是什么。
Supplier<MemoryCacheParams> mBitmapMemoryCacheParamsSupplier
该配置用来表示默认的解码之后的Bitmap的缓存策略,其默认配置如下:
1
2
3
4
5
6
|
// Bitmap 内存缓存参数 Supplier
mBitmapMemoryCacheParamsSupplier
=
builder
.
mBitmapMemoryCacheParamsSupplier
==
null
?
new
DefaultBitmapMemoryCacheParamsSupplier
(
(
ActivityManager
)
builder
.
mContext
.
getSystemService
(
Context
.
ACTIVITY_SERVICE
)
)
:
builder
.
mBitmapMemoryCacheParamsSupplier
;
|
可以看到,如果默认情况下没有在builder中提供mBitmapMemoryCacheParamsSupplier中提供配置的话,会通过DefaultBitmapMemoryCacheParamsSupplier创建一个,那创建的内容是什么呢?DefaultBitmapMemoryCacheParamsSupplier代码比较简单,其配置的MemoryCacheParams内容通过表格简单列举一下。 MemoryCacheParams 配置:
变量名 | 默认值 | 备注 |
---|---|---|
maxCacheSize | 不同内存,cache大小不同,见下表 | cache的最大空间,单位kb |
maxCacheEntries | 256 | cache中允许的有效元素的最大数量 |
maxEvictionQueueSize | Integer.MAX_VALUE | cache待回收空间队列大小,单位kb |
maxEvictionQueueEntries | Integer.MAX_VALUE | cache待回收队列最大元素数量 |
maxCacheEntrySize | Integer.MAX_VALUE | 单个cache所能容纳的最大元素数量 |
不同机器上,所配置的cache大小分别为:
序号 | 内存 | 设定值 | 说明 |
---|---|---|---|
1 | <32MB | 4MB | |
2 | >=32MB && <64MB | 6MB | |
3 | 不在1、2之列 && API < 11 | 8MB | 之前版本使用共享内存无法获得足够理想的效果 |
4 | 不再1、2之列 && API >= 11 | 程序可用Heap大小/4 |
CacheKeyFactory mCacheKeyFactory
CacheKeyFactory的配置代码如下:
1
2
3
4
|
mCacheKeyFactory
=
builder
.
mCacheKeyFactory
==
null
?
DefaultCacheKeyFactory
.
getInstance
(
)
:
builder
.
mCacheKeyFactory
;
|
对于CacheKeyFactory而言,其配置主要分为两类,一类是未解码的ImageRequest,一类是已经解码的ImageRequest,分别如下:
未解码的ImageRquest
对于这种ImageRquest,通过的SimpleCacheKey来实现。
1
2
3
4
|
@Override
public
CacheKey
getEncodedCacheKey
(
ImageRequest
request
)
{
return
new
SimpleCacheKey
(
getCacheKeySourceUri
(
request
.
getSourceUri
(
)
)
.
toString
(
)
)
;
}
|
而实际上,SimpleCache则是简单的对传入的String取.hashCode(),换句话说,就是根据Uri生成了hashCode
解码的ImageRequest
剩余情况下,所使用的参数有:
参数名称 | 参数描述 |
---|---|
mSourceString | 一般对应Uri |
mResizeOptions | 大小调整参数 |
mAutoRotated | 自动旋转参数 |
mImageDecodeOptions | 解码配置 |
mPostprocessorCacheKey | 后处理器CacheKey |
mPostprocessorName | 后处理器名称 |
Supplier<MemoryCacheParams> mEncodedMemoryCacheParams
该变量提供未解码图片缓存配置策略,代码如下:
1
2
3
4
|
mEncodedMemoryCacheParamsSupplier
=
builder
.
mEncodedMemoryCacheParamsSupplier
==
null
?
new
DefaultEncodedMemoryCacheParamsSupplier
(
)
:
builder
.
mEncodedMemoryCacheParamsSupplier
;
|
看看DefaultEncodedMemoryCacheparamsSupplier都配置了什么?其实与CacheKeyFactory mCacheKeyFactory类似。区别在于Cache大小取值不同,具体如下:
序号 | 内存 |
---|---|
<16MB | 1MB |
<32MB | 2MB |
>=64MB | 4MB |
ImageCacheStatsTracker mImageCacheStatsTracker
该配置主要用来控制ImageCache统计信息记录,相关代码如下:
1
2
3
4
|
mImageCacheStatsTracker
=
builder
.
mImageCacheStatsTracker
==
null
?
NoOpImageCacheStatsTracker
.
getInstance
(
)
:
builder
.
mImageCacheStatsTracker
;
|
默认配置为:什么ImageCache的统计信息也不记录。
DiskCacheConfig mMainDiskCacheConfig
磁盘缓存策略配置
1
2
3
4
|
mMainDiskCacheConfig
=
builder
.
mMainDiskCacheConfig
==
null
?
getDefaultMainDiskCacheConfig
(
builder
.
mContext
)
:
builder
.
mMainDiskCacheConfig
;
|
默认配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
private
static
DiskCacheConfig
getDefaultMainDiskCacheConfig
(
final
Context
context
)
{
return
DiskCacheConfig
.
newBuilder
(
)
// 默认文件路径
.
setBaseDirectoryPathSupplier
(
new
Supplier
&
lt
;
File
&
gt
;
(
)
{
@Override
public
File
get
(
)
{
return
context
.
getApplicationContext
(
)
.
getCacheDir
(
)
;
}
}
)
// 目录
.
setBaseDirectoryName
(
"image_cache"
)
// 默认大小 40MB
.
setMaxCacheSize
(
40
*
ByteConstants
.
MB
)
// 磁盘空间不足时候,默认大小 10MB
.
setMaxCacheSizeOnLowDiskSpace
(
10
*
ByteConstants
.
MB
)
// 磁盘控件极其不足时,默认 2MB
.
setMaxCacheSizeOnVeryLowDiskSpace
(
2
*
ByteConstants
.
MB
)
.
build
(
)
;
}
|
NetworkFetcher mNetworkFetcher
NetworkFetcher,Fresco支持okHttp和Android自带的HttpURLConnection实现。
1
2
3
4
|
mNetworkFetcher
=
builder
.
mNetworkFetcher
==
null
?
new
HttpUrlConnectionNetworkFetcher
(
)
:
builder
.
mNetworkFetcher
;
|
网络的获取部分是一个图片库的重要部分,在后面我们需要重点分析,此处知道在默认情况下,Fresco采用Android自带的网络库即可。
PoolFactory mPoolFactory
在图形库当中,由于需要频繁小块的内存访问,重复申请空间会花费大量的时间,因此都会采用对象池/数据池的办法重复利用以前的对象,Fresco也不例外:
1
2
3
4
|
mPoolFactory
=
builder
.
mPoolFactory
==
null
?
new
PoolFactory
(
PoolConfig
.
newBuilder
(
)
.
build
(
)
)
:
builder
.
mPoolFactory
;
|
对应的默认配置代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
private
PoolConfig
(
Builder
builder
)
{
mBitmapPoolParams
=
builder
.
mBitmapPoolParams
==
null
?
DefaultBitmapPoolParams
.
get
(
)
:
builder
.
mBitmapPoolParams
;
mBitmapPoolStatsTracker
=
builder
.
mBitmapPoolStatsTracker
==
null
?
NoOpPoolStatsTracker
.
getInstance
(
)
:
builder
.
mBitmapPoolStatsTracker
;
mFlexByteArrayPoolParams
=
builder
.
mFlexByteArrayPoolParams
==
null
?
DefaultFlexByteArrayPoolParams
.
get
(
)
:
builder
.
mFlexByteArrayPoolParams
;
mMemoryTrimmableRegistry
=
builder
.
mMemoryTrimmableRegistry
==
null
?
NoOpMemoryTrimmableRegistry
.
getInstance
(
)
:
builder
.
mMemoryTrimmableRegistry
;
mNativeMemoryChunkPoolParams
=
builder
.
mNativeMemoryChunkPoolParams
==
null
?
DefaultNativeMemoryChunkPoolParams
.
get
(
)
:
builder
.
mNativeMemoryChunkPoolParams
;
mNativeMemoryChunkPoolStatsTracker
=
builder
.
mNativeMemoryChunkPoolStatsTracker
==
null
?
NoOpPoolStatsTracker
.
getInstance
(
)
:
builder
.
mNativeMemoryChunkPoolStatsTracker
;
mSmallByteArrayPoolParams
=
builder
.
mSmallByteArrayPoolParams
==
null
?
DefaultByteArrayPoolParams
.
get
(
)
:
builder
.
mSmallByteArrayPoolParams
;
mSmallByteArrayPoolStatsTracker
=
builder
.
mSmallByteArrayPoolStatsTracker
==
null
?
NoOpPoolStatsTracker
.
getInstance
(
)
:
builder
.
mSmallByteArrayPoolStatsTracker
;
}
|
依赖来看:
PoolParams mBitmapPoolParams
默认情况下,Fresco不缓存任何Bitmap对象,如果使用完毕,则立刻释放。 PoolParams参数
名称 | 含义 | 默认配置 |
---|---|---|
maxSizeHardCap | 最大实际使用空间,当pool的size达到该设定值时,再申请空间会抛出BasePool.PoolSizeViolationException异常 | 内存>16MB -> 0.75Max; 内存<=16MB -> 0.5Max |
maxSizeSoftCap | 一个pool的虚拟容量: 当pool的size达到该设定值时,pool会尝试清理空间,直至size<该设定值 或者 空闲空间=0< | 0:不缓存 |
bucketSizes | pool可以包含各种各样的「size」,一个bucket用来表示一种大小,额外的,每一中bucket包含max-length,用来表示bucket中used+free的总共的元素数量,此处的maxSize是上面的soft类型的maxSize,如果达到限制,不会抛出异常,而仅仅是开始释放空间,如果此时仍有请求过来,则是和简单的alloc+free一样,不会被pool管理。如果该参数null,那么pool会根据需求自动创建bucket | 0:不缓存 |
minBucketSize | 表示pool中最小的bucket数量,可以保证任何元素小于等于该参数的都可以保存的bucket中 | 0 |
maxBucketSize | 仅有元素size小于该参数时,才会保存至bucket中,如果尺寸超过该参数,会抛出异常。 | Integer.MAX_VALUE |
其他的也是各种Pool的配置,此处就不再多分析,需要的时候再过来看。
ProgressiveJpegConfig
渐进式照片显示控制。
RequestListeners
保存所有的请求监听者对象
ResizeAndRotateEnabledForNetwork
是否允许从网络获取的图像,调整大小/缩放
SmallImageDiskCacheConfig
较小图片的Disk Cache配置
ExecutorSupplier
线程池对象,注意,该对象初始化代码如下:
1
2
3
4
|
int
numCpuBoundThreads
=
mPoolFactory
.
getFlexByteArrayPoolMaxNumThreads
(
)
;
mExecutorSupplier
=
builder
.
mExecutorSupplier
==
null
?
new
DefaultExecutorSupplier
(
numCpuBoundThreads
)
:
builder
.
mExecutorSupplier
;
|
也就是说,这个是依赖于FlexByteArrayPoolMaxNumThreads()的,那么这个方法默认的参数是什么呢?跟进去看一下 FlexByteArrayPool中的线程池数量为:public static final int DEFAULT_MAX_NUM_THREADS = Runtime.getRuntime().availableProcessors();
初始化Drawee
Drawee的初始化代码如下:
1
2
3
4
5
|
// 初始化Drawee
private
static
void
initializeDrawee
(
Context
context
)
{
sDraweeControllerBuilderSupplier
=
new
PipelineDraweeControllerBuilderSupplier
(
context
)
;
SimpleDraweeView
.
initialize
(
sDraweeControllerBuilderSupplier
)
;
}
|
可以看到Drawee的初始化分为两步:
- 实例化PipelineDraweeControllerBuilderSuppplier。
- 使用PipelineDraweeControllerBuilderSupplier初始化SimpleDraweeView。
PipelineDraweeControllerBuilderSupplier
该对象的实例过程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
PipelineDraweeControllerBuilderSupplier
(
Context
context
,
ImagePipelineFactory
imagePipelineFactory
,
Set
&
lt
;
ControllerListener
&
gt
;
boundControllerListeners
)
{
mContext
=
context
;
mImagePipeline
=
imagePipelineFactory
.
getImagePipeline
(
)
;
mPipelineDraweeControllerFactory
=
new
PipelineDraweeControllerFactory
(
context
.
getResources
(
)
,
DeferredReleaser
.
getInstance
(
)
,
imagePipelineFactory
.
getAnimatedDrawableFactory
(
)
,
UiThreadImmediateExecutorService
.
getInstance
(
)
)
;
mBoundControllerListeners
=
boundControllerListeners
;
}
|
步骤如下:
- 获取ImagePipeline
- 实例化PipelineDraweeControllerFactory
- 设置Controller监听者
而PipelineDraweeController则设置了一下的属性
1
2
3
4
5
6
7
8
|
// 资源所在的Resource
private
Resources
mResources
;
// DeferredReleaser 用于释放任务
private
DeferredReleaser
mDeferredReleaser
;
// 动画Drawable工厂
private
AnimatedDrawableFactory
mAnimatedDrawableFactory
;
// 基于主线程的线程池
private
Executor
mUiThreadExecutor
;
|
其中变量的含义比较容易理解,就不再解释,需要注意的是, mUiThreadExecutor是一个封装了主线程Looper的Executor。
SimpleDraweeView的初始化
SimpleDraweeView的初始化更加简单,只有一行代码。
1
2
3
4
|
public
static
void
initialize
(
Supplier
&
lt
;
?
extends
SimpleDraweeControllerBuilder
&
gt
;
draweeControllerBuilderSupplier
)
{
sDraweeControllerBuilderSupplier
=
draweeControllerBuilderSupplier
;
}
|
就是将前面初始化好的 PipelineDraweeControllerBuilderSupplier 设置给SimpleDraweeView.
好了,Fresco最基本的初始化过程就是这些,但这些还不能向我们解释,Fresco具体是将图片怎么样绘制到界面上的,在下一篇文章中,将对这些内容进行分析。
转载自闭门造车