下面从Image Pipeline入手分析其相关的代码,并追溯到和数据源,数据订阅者的关联,以求 一脉相承地记叙,便于理解。
Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要做的每个事情。
Fresco初始化完成两部分内容:
1 | public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig) { |
1)initializeDrawee(context);1
2
3
4private static void initializeDrawee(Context context) {
sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}
2)Image pipeline的初始化:ImagePipelineFactory.initialize(imagePipelineConfig);
ImagePipelineConfig管理image pipeline的配置。
Builder设计模式,可配置的信息如下:
Fresco的getImagePipeline()方法:
1 | ImagePipelineFactory.getInstance().getImagePipeline() |
ImagePipelineFactory的getImagePipeline()方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public ImagePipeline getImagePipeline() {
if (mImagePipeline == null) {
mImagePipeline =
new ImagePipeline(
getProducerSequenceFactory(),
mConfig.getRequestListeners(),
mConfig.getIsPrefetchEnabledSupplier(),
getBitmapMemoryCache(),
getEncodedMemoryCache(),
getMainBufferedDiskCache(),
getSmallImageBufferedDiskCache(),
mConfig.getCacheKeyFactory());
}
return mImagePipeline;
}
下面是PipelineDraweeController和Image pipeline建立联系的过程:
PipelineDraweeController:
Drawee controller是image pipeline和SettableDraweeHierarchy的桥梁。
PipelineDraweeController是PipelineDraweeControllerFactory.newController()创建的。
PipelineDraweeControllerBuilder的obtainController()方法:
1 | protected PipelineDraweeController obtainController() { |
PipelineDraweeControllerBuilder是通过PipelineDraweeControllerBuilderSupplier提供的:
PipelineDraweeControllerBuilderSupplier构造方法:1
2
3
4
5
6
7
8
9
10
11
12
13public PipelineDraweeControllerBuilderSupplier(
Context context,
ImagePipelineFactory imagePipelineFactory,
Set<ControllerListener> boundControllerListeners) {
mContext = context;
mImagePipeline = imagePipelineFactory.getImagePipeline();
mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory(
context.getResources(),
DeferredReleaser.getInstance(),
imagePipelineFactory.getAnimatedDrawableFactory(),
UiThreadImmediateExecutorService.getInstance());
mBoundControllerListeners = boundControllerListeners;
}
PipelineDraweeControllerBuilderSupplier的get()方法:1
2
3
4
5
6
7public PipelineDraweeControllerBuilder get() {
return new PipelineDraweeControllerBuilder(
mContext,
mPipelineDraweeControllerFactory,
mImagePipeline,
mBoundControllerListeners);
}
PipelineDraweeControllerBuilder中的getDataSourceForRequest()方法:
根据不同的图片请求返回不同的数据源。1
2
3
4
5
6
7
8
9
10
11
12
13
14@Override
public PipelineDraweeControllerBuilder setUri(Uri uri) {
return super.setImageRequest(ImageRequest.fromUri(uri));
}
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
boolean bitmapCacheOnly) {
if (bitmapCacheOnly) {
return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext);
} else {
return mImagePipeline.fetchDecodedImage(imageRequest, callerContext);
}
}
ImageRequest:封装了Image Pipeline处理被请求的图片的所有相关信息且不能修改内容。可通过ImageRequestBuilder初始化。
1 | protected ImageRequest(ImageRequestBuilder builder) {} |
1 | public static ImageRequestBuilder newBuilderWithSource(Uri uri) { |
或者直接用fromUri()方法初始化:
1 | public static ImageRequest fromUri(@Nullable Uri uri) { |
ImageRequest可以设置的信息如下:
ImageType:设置大小文件缓存;详情见官方文档
SourceUri:图片源Uri;
SourceFile:图片文件地址;
ProgressiveRenderingEnabled 若为true,则这个图片请求会返回质量递进的几次图片信息(渐进式图片);
LocalThumbnailPreviewsEnabled 若为true,则这个图片请求会在访问本地图片时先返回一个缩略图;
ResizeOptions 缩放尺寸,仅支持JPEG,而且不是每次都需要在ImageRequest中设置缩放尺寸的;
AutoRotateEnabled 是否允许图片旋转;关于旋转和缩放
RequestPriority 这个请求的优先级:
LowestPermittedRequestLevel 最低允许从哪层缓存中取数据,关于图片请求
IsDiskCacheEnabled 若为false,则此图片请求不会从文件缓存中获取数据;
PostProcessor 在图片请求成功之后对图片的处理操作;关于修改图片
现在回过头来继续分析这段代码:
1 | if (bitmapCacheOnly) { |
bitmapCacheOnly:是否只从已解码的内存缓存中获取数据;
如果是,执行fetchImageFromBitmapCache()方法:
1 | public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache( |
如果不是执行fetchDecodedImage()方法:
ImageRequest.RequestLevel.FULL_FETCH;
枚举RequestLevel的四个主要参数对应着四种缓存行为:1
2
3
4
5
6
7
8/* Fetch (from the network or local storage) */
FULL_FETCH(1),
/* Disk caching */
DISK_CACHE(2),
/* Encoded memory caching 未解码的缓存*/
ENCODED_MEMORY_CACHE(3),
/* Bitmap caching 已经解码的缓存*/
BITMAP_MEMORY_CACHE(4);
同时也对应着Image Pipeline工作流程:
1)检查内存缓存,如有,返回
2)后台线程开始后续工作
3)检查是否在未解码内存缓存中。如有,解码,变换,返回,然后缓存到内存缓存中。
4)检查是否在文件缓存中,如果有,变换,返回。缓存到未解码缓存和内存缓存中。
5)从网络或者本地加载。加载完成后,解码,变换,返回。存到各个缓存中。
首先,我们看到数据是包装在CloseableReference中的。有关于数据源和数据订阅者1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache(
ImageRequest imageRequest,
Object callerContext) {
try {
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
return submitFetchRequest(
producerSequence,
imageRequest,
ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE,
callerContext);
} catch (Exception exception) {
return DataSources.immediateFailedDataSource(exception);
}
}
这部分代码会在后续的文章中分析。