Fresco源码分析三

下面从Image Pipeline入手分析其相关的代码,并追溯到和数据源,数据订阅者的关联,以求 一脉相承地记叙,便于理解。

Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要做的每个事情。

Fresco初始化完成两部分内容:

1
2
3
4
public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig) {
ImagePipelineFactory.initialize(imagePipelineConfig);
initializeDrawee(context);
}

1)initializeDrawee(context);

1
2
3
4
private 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
15
public 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected PipelineDraweeController obtainController() {
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
controller = (PipelineDraweeController) oldController;
controller.initialize(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCallerContext());
} else {
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCallerContext());
}
return controller;
}

PipelineDraweeControllerBuilder是通过PipelineDraweeControllerBuilderSupplier提供的:
PipelineDraweeControllerBuilderSupplier构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
public 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
7
public 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
2
3
public static ImageRequestBuilder newBuilderWithSource(Uri uri) {
return new ImageRequestBuilder().setSource(uri);
}

或者直接用fromUri()方法初始化:

1
2
3
public static ImageRequest fromUri(@Nullable Uri uri) {
return (uri == null) ? null : ImageRequestBuilder.newBuilderWithSource(uri).build();
}

ImageRequest可以设置的信息如下:
ImageType:设置大小文件缓存;详情见官方文档
SourceUri:图片源Uri;
SourceFile:图片文件地址;
ProgressiveRenderingEnabled 若为true,则这个图片请求会返回质量递进的几次图片信息(渐进式图片);
LocalThumbnailPreviewsEnabled 若为true,则这个图片请求会在访问本地图片时先返回一个缩略图;
ResizeOptions 缩放尺寸,仅支持JPEG,而且不是每次都需要在ImageRequest中设置缩放尺寸的;
AutoRotateEnabled 是否允许图片旋转;关于旋转和缩放
RequestPriority 这个请求的优先级:
LowestPermittedRequestLevel 最低允许从哪层缓存中取数据,关于图片请求
IsDiskCacheEnabled 若为false,则此图片请求不会从文件缓存中获取数据;
PostProcessor 在图片请求成功之后对图片的处理操作;关于修改图片

现在回过头来继续分析这段代码:

1
2
3
4
if (bitmapCacheOnly) {
return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext);
} else {
return mImagePipeline.fetchDecodedImage(imageRequest, callerContext);

bitmapCacheOnly:是否只从已解码的内存缓存中获取数据;
如果是,执行fetchImageFromBitmapCache()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public 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);
}
}

如果不是执行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
15
public 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);
}
}

这部分代码会在后续的文章中分析。

参考文章:https://github.com/desmond1121/Fresco-Source-Analysis

文章目录