前言
之前一直使用的是 Glide 图片加载框架, 最近接触了 Fresco 这款出自 Facebook 的图片加载框架, 为了方便后期对其进行封装与拓展, 这里分析记录一下它的一次简单的加载流程
关于 Fresco 的简单使用可以参考 Fresco 使用文档, 与 Glide 不同, 它主要是通过 DraweeView 对上层提供便捷性的服务, 文章主体分为如下几个部分
- Fresco 初始化
- SimpleDraweeView 的创建
- 数据的加载
一. Fresco 初始化
public class Fresco {
private static volatile boolean sIsInitialized = false;
public static void initialize(Context context) {
initialize(context, null, null);
}
public static void initialize(
Context context,
@Nullable ImagePipelineConfig imagePipelineConfig,
@Nullable DraweeConfig draweeConfig) {
// 用于保证只初始化一次
if (sIsInitialized) {
......
} else {
sIsInitialized = true;
}
// 1. 加载 so 库
try {
SoLoader.init(context, 0);
} catch (IOException e) {
......
}
// we should always use the application context to avoid memory leaks
context = context.getApplicationContext();
// 2. 初始化 ImagePipeline 的构造工厂
if (imagePipelineConfig == null) {
ImagePipelineFactory.initialize(context);
} else {
ImagePipelineFactory.initialize(imagePipelineConfig);
}
// 3. 初始化 Drawee
initializeDrawee(context, draweeConfig);
}
}
可以看到 Fresco 的初始化过程做了如下事情
- 利用 SoLoader 加载 so 库
- 初始化 ImagePipeline 的构造工厂
- 初始化 Drawee
一) 初始化 ImagePipeline 工厂
public class ImagePipelineFactory {
private static ImagePipelineFactory sInstance = null;
private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;
public static void initialize(Context context) {
initialize(ImagePipelineConfig.newBuilder(context).build());
}
public static void initialize(ImagePipelineConfig imagePipelineConfig) {
sInstance = new ImagePipelineFactory(imagePipelineConfig);
}
private final ImagePipelineConfig mConfig;
private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;
public ImagePipelineFactory(ImagePipelineConfig config) {
// 存储 Pipeline 的配置
mConfig = Preconditions.checkNotNull(config);
// 创建一个使用队列维护 Runnable 的 Execute, 方便控制 Runnable 交由 Executor 的执行时机
mThreadHandoffProducerQueue = new ThreadHandoffProducerQueue(
// 获取线程池提供者
config.getExecutorSupplier().forLightweightBackgroundTasks()
);
}
}
ImpagePipelineFactory 可以理解为一个抽象工厂, 负责生产一些列与 ImagePipeline 相关的对象, 对后续数据编解码提供支持
二) 初始化 Drawee
public class Fresco {
private static PipelineDraweeControllerBuilderSupplier sDraweeControllerBuilderSupplier;
/** Initializes Drawee with the specified config. */
private static void initializeDrawee(
Context context,
@Nullable DraweeConfig draweeConfig) {
// 创建 DraweeController 的 Builder 提供器
sDraweeControllerBuilderSupplier =
new PipelineDraweeControllerBuilderSupplier(context, draweeConfig);
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}
}
1. 创建 PipelineDraweeControllerBuilderSupplier
public class PipelineDraweeControllerBuilderSupplier implements
Supplier<PipelineDraweeControllerBuilder> {
private final Context mContext;
private final ImagePipeline mImagePipeline;
private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;
private final Set<ControllerListener> mBoundControllerListeners;
public PipelineDraweeControllerBuilderSupplier(
Context context,
ImagePipelineFactory imagePipelineFactory,
Set<ControllerListener> boundControllerListeners,
@Nullable DraweeConfig draweeConfig) {
mContext = context;
mImagePipeline = imagePipelineFactory.getImagePipeline();
if (draweeConfig != null && draweeConfig.getPipelineDraweeControllerFactory() != null) {
mPipelineDraweeControllerFactory = draweeConfig.getPipelineDraweeControllerFactory();
} else {
// 创建默认的工厂对象
mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory();
}
// 初始化 mPipelineDraweeControllerFactory 工厂, 为 PipelineDraweeControllerBuilder 创建 PipelineDraweeController 提供支持
mPipelineDraweeControllerFactory.init(
context.getResources(),
DeferredReleaser.getInstance(),
imagePipelineFactory.getAnimatedDrawableFactory(context),
UiThreadImmediateExecutorService.getInstance(),
mImagePipeline.getBitmapMemoryCache(),
draweeConfig != null
? draweeConfig.getCustomDrawableFactories()
: null,
draweeConfig != null
? draweeConfig.getDebugOverlayEnabledSupplier()
: null);
mBoundControllerListeners = boundControllerListeners;
}
}
PipelineDraweeControllerBuilderSupplier 中持有了 ImagePipeline 和 PipelineDraweeControllerFactory 两个非常重要的对象, 为后续构建 PiplelineDraweeController 提供支持, 这个我们到后面在具体分析
2. 初始化 SimpleDraweeView
关于 initializeDrawee 的过程, 它主要是将 PipelineDraweeControllerBuilderSupplier 注入 SimpleDraweeView
public class SimpleDraweeView extends GenericDraweeView {
private static Supplier<? extends AbstractDraweeControllerBuilder>
sDraweecontrollerbuildersupplier;
/** Initializes {@link SimpleDraweeView} with supplier of Drawee controller builders. */
public static void initialize(
Supplier<? extends AbstractDraweeControllerBuilder> draweeControllerBuilderSupplier) {
sDraweecontrollerbuildersupplier = draweeControllerBuilderSupplier;
}
}
三) 回顾
Fresco 的初始化流程主要如下
- 加载 Fresco 的 so 库
- 构建 ImagePipelineFactory 对后续对图像的编解码提供支持
- 初始化 Drawee
- 创建 PipelineDraweeControllerBuilderSupplier 用于提供 PipelineDraweeControllerBuilder 对象
- 持有 ImagePipeline 和 PipelineDraweeControllerFactory 两个非常重要的对象
- 为 SimpleDraweeView 注入 Supplier, 方便 SimpleDraweeView 构建 DraweeControllerBuilder.
- 创建 PipelineDraweeControllerBuilderSupplier 用于提供 PipelineDraweeControllerBuilder 对象
二. SimpleDraweeView 的创建
public class SimpleDraweeView extends GenericDraweeView {
public SimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
// 父类初始化
super(context, attrs, defStyle);
// 4. 解析一些提供的属性
init(context, attrs);
}
}
public class GenericDraweeView extends DraweeView<GenericDraweeHierarchy> {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public GenericDraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
inflateHierarchy(context, attrs);
}
protected void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
// 获取层级构造器
GenericDraweeHierarchyBuilder builder =
GenericDraweeHierarchyInflater.inflateBuilder(context, attrs);
// 2. 设置期望的比例
setAspectRatio(builder.getDesiredAspectRatio());
// 3. 创建 GenericDraweeHierarchy 并注入 DraweeView
setHierarchy(builder.build());
}
}
public class DraweeView<DH extends DraweeHierarchy> extends ImageView {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public DraweeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context,attrs,defStyleAttr,defStyleRes);
init(context);
}
/** This method is idempotent so it only has effect the first time it's called */
private void init(Context context) {
if (mInitialised) {
return;
}
mInitialised = true;
// 1. 创建 DraweeHolder
mDraweeHolder = DraweeHolder.create(null, context);
......
}
}
SimpleDraweeView 中只做了一些简单的属性解析, 其具体的初始化流程依靠的是父类
- 创建 DraweeHolder
- 设置期望的比例
- 创建 GenericDraweeHierarchy 并注入 DraweeView
- 解析 View 的属性
这里我们主要 focus DraweeHolder 的创建和 GenericDraweeHierarchy 的创建过程
一) 创建 DraweeHolder
public class DraweeHolder<DH extends DraweeHierarchy>
implements VisibilityCallback {
public static <DH extends DraweeHierarchy> DraweeHolder<DH> create(
@Nullable DH hierarchy,
Context context) {
// 以 hierarchy 为入参, 创建 Holder 对象
DraweeHolder<DH> holder = new DraweeHolder<DH>(hierarchy);
// 处理与 context 相关的数据
holder.registerWithContext(context);
return holder;
}
/**
* Creates a new instance of DraweeHolder.
* @param hierarchy
*/
public DraweeHolder(@Nullable DH hierarchy) {
// 通过 DraweeView 的 init 方法可知, 这个 hierarchy 目前为 null
if (hierarchy != null) {
setHierarchy(hierarchy);
}
}
private DH mHierarchy;
public void setHierarchy(DH hierarchy) {
final boolean isControllerValid = isControllerValid();
......
// 存储到成员变量中
mHierarchy = Preconditions.checkNotNull(hierarchy);
// 获取最顶层的 Drawable
Drawable drawable = mHierarchy.getTopLevelDrawable();
onVisibilityChange(drawable == null || drawable.isVisible());
setVisibilityCallback(this);
// 为 Controller 绑定 Hierarchy
if (isControllerValid) {
mController.setHierarchy(hierarchy);
}
}
}
可以看到 DraweeHolder.create 实例化 DraweeHolder 的过程主要会尝试注入 DraweeHierarchy, 这意味着 DraweeHolder 所要 Hold 的对象即 DraweeHierarchy
接下来我们看看 GenericDraweeHierarchy 的构建
二) 创建 GenericDraweeHierarchy
GenericDraweeHierarchy 的构建是由 GenericDraweeHierarchyBuilder.build 完成
public class GenericDraweeHierarchyBuilder {
......
/**
* Builds the hierarchy.
*/
public GenericDraweeHierarchy build() {
validate();
return new GenericDraweeHierarchy(this);
}
}
下面看看 GenericDraweeHierarchy 的构造函数中做了哪些处理
public class GenericDraweeHierarchy implements SettableDraweeHierarchy {
private static final int BACKGROUND_IMAGE_INDEX = 0;
private static final int PLACEHOLDER_IMAGE_INDEX = 1;
private static final int ACTUAL_IMAGE_INDEX = 2;
private static final int PROGRESS_BAR_IMAGE_INDEX = 3;
private static final int RETRY_IMAGE_INDEX = 4;
private static final int FAILURE_IMAGE_INDEX = 5;
private static final int OVERLAY_IMAGES_INDEX = 6;
private final Drawable mEmptyActualImageDrawable = new ColorDrawable(Color.TRANSPARENT);
private final Resources mResources;
private @Nullable RoundingParams mRoundingParams;
private final RootDrawable mTopLevelDrawable;
private final FadeDrawable mFadeDrawable;
private final ForwardingDrawable mActualImageWrapper;
GenericDraweeHierarchy(GenericDraweeHierarchyBuilder builder) {
// 资源信息
mResources = builder.getResources();
// 计算要叠加额外叠加的层级
int numOverlays = (builder.getOverlays() != null) ? builder.getOverlays().size() : 1;
numOverlays += (builder.getPressedStateOverlay() != null) ? 1 : 0;
// 要叠加的总层级 = 通用层级 + 额外层级
int numLayers = OVERLAY_IMAGES_INDEX + numOverlays;
// 1. 创建一个 Drawable 数组, 填充通用层级特定的 Drawable 对象
Drawable[] layers = new Drawable[numLayers];
// 2. 初始化通用层级
// 2.1 创建背景 Drawable
layers[BACKGROUND_IMAGE_INDEX] = buildBranch(builder.getBackground(), null);
// 2.2 占位 Drawable
layers[PLACEHOLDER_IMAGE_INDEX] = buildBranch(
builder.getPlaceholderImage(),
builder.getPlaceholderImageScaleType());
// 2.3 真实 Drawable
mActualImageWrapper = new ForwardingDrawable(mEmptyActualImageDrawable);
layers[ACTUAL_IMAGE_INDEX] = buildActualImageBranch(
mActualImageWrapper,
builder.getActualImageScaleType(),
builder.getActualImageFocusPoint(),
builder.getActualImageColorFilter());
// 2.4 加载进度条的 Drawable
layers[PROGRESS_BAR_IMAGE_INDEX] = buildBranch(
builder.getProgressBarImage(),
builder.getProgressBarImageScaleType());
// 2.5 点击重试的 Drawable
layers[RETRY_IMAGE_INDEX] = buildBranch(
builder.getRetryImage(),
builder.getRetryImageScaleType());
// 2.6 加载失败的 Drawable
layers[FAILURE_IMAGE_INDEX] = buildBranch(
builder.getFailureImage(),
builder.getFailureImageScaleType());
// 3. 初始化额外叠加的层级
if (numOverlays > 0) {
int index = 0;
// 3.1 实例化额外的层级
if (builder.getOverlays() != null) {
for (Drawable overlay : builder.getOverlays()) {
layers[OVERLAY_IMAGES_INDEX + index++] = buildBranch(overlay, null);
}
} else {
index = 1; // reserve space for one overlay
}
// 3.2 保证按压效果的 Drawable 在最顶层
if (builder.getPressedStateOverlay() != null) {
layers[OVERLAY_IMAGES_INDEX + index] = buildBranch(builder.getPressedStateOverlay(), null);
}
}
// 4. 将所有的层级封装到 FadeDrawable 中
mFadeDrawable = new FadeDrawable(layers);
mFadeDrawable.setTransitionDuration(builder.getFadeDuration());
// 5. 若需要圆角, 则对 FadeDrawable 进行包装
// 圆角参数
mRoundingParams = builder.getRoundingParams();
Drawable maybeRoundedDrawable =
WrappingUtils.maybeWrapWithRoundedOverlayColor(mFadeDrawable, mRoundingParams);
// 6. 构建最终的 Drawable
mTopLevelDrawable = new RootDrawable(maybeRoundedDrawable);
mTopLevelDrawable.mutate();
// 7. 重置 FadeDrawable 的状态
resetFade();
}
}
看到这里我们就清楚了 GenericDraweeHierarchy 的职责了, 它负责创建和组织需要上屏的 Drawable 集合, 层级如下
- RootDrawable
- RoundedDrawable
- FadeDrawable
- FadeDrawable
- 按压的 Drawable
- Overlay 的 Drawables
- 失败 Drawable: ScaleTypeDrawable
- 重试 Drawable: ScaleTypeDrawable
- 进度条 Drawable: maybe null
- 真实目标的 Drawable: ScaleTypeDrawable(提供 ScaleType 缩放能力)
- ForwardingDrawable (包装一下, 提供拓展空间)
- Drawable(用户设置的)
- ForwardingDrawable (包装一下, 提供拓展空间)
- 展位图 Drawable: ScaleTypeDrawable
- 背景 Drawable
- RoundedDrawable
三) 回顾
SimpleDraweeView 的创建流程如下
- 创建 DraweeHolder
- 持有 DraweeHierarchy
- 创建 GenericDraweeHierarchy
- RootDrawable
- RoundedDrawable
- FadeDrawable
- FadeDrawable
- 按压的 Drawable
- Overlay 的 Drawables
- 失败 Drawable: ScaleTypeDrawable
- 重试 Drawable: ScaleTypeDrawable
- 进度条 Drawable: maybe null
- 真实目标的 Drawable: ScaleTypeDrawable(提供 ScaleType 缩放能力)
- ForwardingDrawable (包装一下, 提供拓展空间)
- Drawable(用户设置的)
- ForwardingDrawable (包装一下, 提供拓展空间)
- 展位图 Drawable: ScaleTypeDrawable
- 背景 Drawable
- RoundedDrawable
- RootDrawable
- 将 GenericDraweeHierarchy 注入 Holder 中暂存
三. 数据的加载
经过了上面两个步骤, Fresco 的资源就初始化好了, 我们只需要在应用层设置一个 Controller, 就可以触发图片的加载了
val controller = Fresco.newDraweeControllerBuilder()
// 构建 ImageRequest, 表示配置请求图片信息
.setImageRequest(
ImageRequestBuilder.newBuilderWithSource(Uri.parse("xxx"))
// 在 ImagePipeline 解码时改变内存中图片的大小
.setResizeOptions(ResizeOptions.forDimensions(100, 100))
// 根据图片信息自动旋转
.setRotationOptions(RotationOptions.autoRotate())
.build()
)
.build()
// 注入加载控制器
draweeView.controller = controller
DraweeController 中提供的参数非常丰富, 更多使用方式可以参考 Fresco Controller
这里的 Controller 为 PipelineDraweeController, 我们先看看它的实例化过程
一) PipelineDraweeController 的创建
public class Fresco {
/** Returns a new instance of Fresco Drawee controller builder. */
public static PipelineDraweeControllerBuilder newDraweeControllerBuilder() {
return sDraweeControllerBuilderSupplier.get();
}
}
sDraweeControllerBuilderSupplier 的实例化, 我们在 Fresco 初始化的时候已经分析过了, 它是一个 PipelineDraweeControllerBuilderSupplier 对象, 这里看看它获取 PipelineDraweeControllerBuilder 的流程
1. PipelineDraweeControllerBuilderSupplier 获取 PipelineDraweeControllerBuilder 对象
public class PipelineDraweeControllerBuilderSupplier implements
Supplier<PipelineDraweeControllerBuilder> {
private final Context mContext;
private final ImagePipeline mImagePipeline;
private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;
private final Set<ControllerListener> mBoundControllerListeners;
@Override
public PipelineDraweeControllerBuilder get() {
// 创建了 PipelineDraweeControllerBuilder
return new PipelineDraweeControllerBuilder(
mContext,
mPipelineDraweeControllerFactory,
mImagePipeline,
mBoundControllerListeners);
}
}
get 方法直接创建了一个 PipelineDraweeControllerBuilder 对象
public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
PipelineDraweeControllerBuilder,
ImageRequest,
CloseableReference<CloseableImage>,
ImageInfo> {
private final ImagePipeline mImagePipeline;
private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;
......
public PipelineDraweeControllerBuilder(
Context context,
PipelineDraweeControllerFactory pipelineDraweeControllerFactory,
ImagePipeline imagePipeline,
Set<ControllerListener> boundControllerListeners) {
// 父类初始化
super(context, boundControllerListeners);
// 将 ImagePipleline 和 PipelineDraweeControllerFactory 注入成员变量
mImagePipeline = imagePipeline;
mPipelineDraweeControllerFactory = pipelineDraweeControllerFactory;
}
}
public abstract class AbstractDraweeControllerBuilder <
BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
REQUEST,
IMAGE,
INFO>
implements SimpleDraweeControllerBuilder {
// components
private final Context mContext;
private final Set<ControllerListener> mBoundControllerListeners;
......
protected AbstractDraweeControllerBuilder(
Context context,
Set<ControllerListener> boundControllerListeners) {
// 将形参注入成员变量
mContext = context;
mBoundControllerListeners = boundControllerListeners;
init();
}
/** Initializes this builder. */
private void init() {
// 重置成员变量
......
}
}
PipelineDraweeControllerBuilder 实例化过程即将形参注入成员变量, 并没有做额外的逻辑操作
下面我们看看 PipelineDraweeControllerBuilder.build() 是如何创建 PipelineDraweeController 的
2. PipelineDraweeControllerBuilder 构造 PipelineDraweeController 对象
public abstract class AbstractDraweeControllerBuilder <
BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
REQUEST,
IMAGE,
INFO>
implements SimpleDraweeControllerBuilder {
/** Builds the specified controller. */
@Override
public AbstractDraweeController build() {
......
// if only a low-res request is specified, treat it as a final request.
if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) {
mImageRequest = mLowResImageRequest;
mLowResImageRequest = null;
}
// 1. 将构建工作转发给了 buildController
return buildController();
}
/** Builds a regular controller. */
protected AbstractDraweeController buildController() {
// 2. 获取 Controller 对象
AbstractDraweeController controller = obtainController();
controller.setRetainImageOnFailure(getRetainImageOnFailure());
controller.setContentDescription(getContentDescription());
......
return controller;
}
@ReturnsOwnership protected abstract AbstractDraweeController obtainController();
}
这里会调用 obtainController 方法来获取一个 AbstractDraweeController 对象, 这是一个抽象方法, 它的具体实现如下
public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
PipelineDraweeControllerBuilder,
ImageRequest,
CloseableReference<CloseableImage>,
ImageInfo> {
@Override
protected PipelineDraweeController obtainController() {
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
....
} else {
// 交由工厂执行构造操作
controller =
mPipelineDraweeControllerFactory.newController(
// 获取 Supplier<DataSource<CloseableReference<CloseableImage>>>
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories,
mImageOriginListener);
}
return controller;
}
}
Builder 最终会调用 Factory 去执行 PiplelineDraweeController 的创建, 在分析其创建之前, 我们需要关注 obtainDataSourceSupplier 这个方法, 它是用户想要加载数据源的提供器, 下面看看它的实现
1) 构建 DataSource 提供器
public abstract class AbstractDraweeControllerBuilder <
BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
REQUEST,
IMAGE,
INFO>
implements SimpleDraweeControllerBuilder {
/** Gets the top-level data source supplier to be used by a controller. */
protected Supplier<DataSource<IMAGE>> obtainDataSourceSupplier() {
if (mDataSourceSupplier != null) {
return mDataSourceSupplier;
}
Supplier<DataSource<IMAGE>> supplier = null;
// final image supplier;
if (mImageRequest != null) {
// 通过 Request 构建 DataSourceSupplier
supplier = getDataSourceSupplierForRequest(mImageRequest);
} else if (mMultiImageRequests != null) {
supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests, mTryCacheOnlyFirst);
}
......
return supplier;
}
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(REQUEST imageRequest) {
return getDataSourceSupplierForRequest(imageRequest, CacheLevel.FULL_FETCH);
}
protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(
final REQUEST imageRequest,
final CacheLevel cacheLevel) {
final Object callerContext = getCallerContext();
// 构建了一个一个 DataSource 类型的 Supplier
return new Supplier<DataSource<IMAGE>>() {
@Override
public DataSource<IMAGE> get() {
// 获取 DataSource
return getDataSourceForRequest(imageRequest, callerContext, cacheLevel);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("request", imageRequest.toString())
.toString();
}
};
}
}
public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
PipelineDraweeControllerBuilder,
ImageRequest,
CloseableReference<CloseableImage>,
ImageInfo> {
@Override
protected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest(
ImageRequest imageRequest,
Object callerContext,
AbstractDraweeControllerBuilder.CacheLevel cacheLevel) {
return mImagePipeline.fetchDecodedImage(
imageRequest,
callerContext,
convertCacheLevelToRequestLevel(cacheLevel));
}
}
可以看到 Supplier
2) 工厂实例化 PipelineDraweeController 对象
public class PipelineDraweeControllerFactory {
public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories,
@Nullable ImageOriginListener imageOriginListener) {
// 实例化 PipelineDraweeController 对象
PipelineDraweeController controller =
internalCreateController(
mResources,
mDeferredReleaser,
mAnimatedDrawableFactory,
mUiThreadExecutor,
mMemoryCache,
mDrawableFactories,
customDrawableFactories,
dataSourceSupplier,
id,
cacheKey,
callerContext);
......
controller.setImageOriginListener(imageOriginListener);
return controller;
}
protected PipelineDraweeController internalCreateController(
Resources resources,
DeferredReleaser deferredReleaser,
DrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor,
MemoryCache<CacheKey, CloseableImage> memoryCache,
@Nullable ImmutableList<DrawableFactory> globalDrawableFactories,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories,
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext) {
// 直接 new 了一个对象
PipelineDraweeController controller =
new PipelineDraweeController(
resources,
deferredReleaser,
animatedDrawableFactory,
uiThreadExecutor,
memoryCache,
dataSourceSupplier,
id,
cacheKey,
callerContext,
globalDrawableFactories);
controller.setCustomDrawableFactories(customDrawableFactories);
return controller;
}
}
下面我们看看这个 PipelineDraweeController 实例化的时候做了哪些操作
public class PipelineDraweeController
extends AbstractDraweeController<CloseableReference<CloseableImage>, ImageInfo> {
private final Resources mResources;
private final DrawableFactory mAnimatedDrawableFactory;
private @Nullable MemoryCache<CacheKey, CloseableImage> mMemoryCache;
private CacheKey mCacheKey;
private final ImmutableList<DrawableFactory> mGlobalDrawableFactories;
public PipelineDraweeController(
Resources resources,
DeferredReleaser deferredReleaser,
DrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor,
MemoryCache<CacheKey, CloseableImage> memoryCache,
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext,
@Nullable ImmutableList<DrawableFactory> globalDrawableFactories) {
// 父类初始化
super(deferredReleaser, uiThreadExecutor, id, callerContext);
// 将参数注入成员变量
mResources = resources;
mAnimatedDrawableFactory = animatedDrawableFactory;
mMemoryCache = memoryCache;
mCacheKey = cacheKey;
mGlobalDrawableFactories = globalDrawableFactories;
init(dataSourceSupplier);
}
// Constant state (non-final because controllers can be reused)
private Supplier<DataSource<CloseableReference<CloseableImage>>> mDataSourceSupplier;
private void init(Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier) {
mDataSourceSupplier = dataSourceSupplier;
}
}
PipelineDraweeController 的构造函数并没有做什么特殊的事务, 它将形参中的数据暂存到了成员变量中
其中需要我们特别注意的是 mDataSourceSupplier, 它是数据源的提供者承担着数据加载的重任
下面我们看看它的父类是如何初始化的
public abstract class AbstractDraweeController<T, INFO> implements
DraweeController,
DeferredReleaser.Releasable,
GestureDetector.ClickListener {
public AbstractDraweeController(
DeferredReleaser deferredReleaser,
Executor uiThreadImmediateExecutor,
String id,
Object callerContext) {
mDeferredReleaser = deferredReleaser;
mUiThreadImmediateExecutor = uiThreadImmediateExecutor;
// 执行初始化操作
init(id, callerContext, true);
}
private void init(String id, Object callerContext, boolean justConstructed) {
mEventTracker.recordEvent(Event.ON_INIT_CONTROLLER);
// cancel deferred release
if (!justConstructed && mDeferredReleaser != null) {
mDeferredReleaser.cancelDeferredRelease(this);
}
// 重置状态
mIsAttached = false;
mIsVisibleInViewportHint = false;
releaseFetch();
mRetainImageOnFailure = false;
// 重新初始化 mRetryManager
if (mRetryManager != null) {
mRetryManager.init();
}
// 重置手势探测器
if (mGestureDetector != null) {
mGestureDetector.init();
mGestureDetector.setClickListener(this);
}
// 重置 mControllerListener
if (mControllerListener instanceof InternalForwardingListener) {
((InternalForwardingListener) mControllerListener).clearListeners();
} else {
mControllerListener = null;
}
mControllerViewportVisibilityListener = null;
// 清空之前绑定的 DraweeHierarchy
if (mSettableDraweeHierarchy != null) {
mSettableDraweeHierarchy.reset();
mSettableDraweeHierarchy.setControllerOverlay(null);
mSettableDraweeHierarchy = null;
}
mControllerOverlay = null;
// reinitialize constant state
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(TAG, "controller %x %s -> %s: initialize", System.identityHashCode(this), mId, id);
}
mId = id;
mCallerContext = callerContext;
}
}
可以看到 PipelineDraweeController 初始化的操作主要是为成员变量赋初值, 以及重置可变状态的数据
3. 回顾
二) 为 DraweeView 注入 Controller
这里我们就看看 setController 的时候如何加载 uri 对应的图片, 这个方法直接定义在 DraweeView 中
public class DraweeView<DH extends DraweeHierarchy> extends ImageView {
/** Sets the controller. */
public void setController(@Nullable DraweeController draweeController) {
// 为 DraweeHolder 注入 Controller
mDraweeHolder.setController(draweeController);
// 获取顶层的 Hierarchy 的 Drawable, 让 ImageView 展示
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
}
}
可以看到 DraweeView 将注入 Controller 的动作分发给了 DraweeHolder, 其实现如下
public class DraweeHolder<DH extends DraweeHierarchy>
implements VisibilityCallback {
/**
* Sets a new controller.
*/
public void setController(@Nullable DraweeController draweeController) {
// 1. 解绑之前的 Controller
boolean wasAttached = mIsControllerAttached;
if (wasAttached) {
detachController();
}
// 2. 让之前 Controller 与 Hierarchy 解绑
if (isControllerValid()) {
mEventTracker.recordEvent(Event.ON_CLEAR_OLD_CONTROLLER);
mController.setHierarchy(null);
}
// 3, 更新 mController 对象
mController = draweeController;
if (mController != null) {
mEventTracker.recordEvent(Event.ON_SET_CONTROLLER);
// 3.1 绑定 Hierarchy
mController.setHierarchy(mHierarchy);
} else {
mEventTracker.recordEvent(Event.ON_CLEAR_CONTROLLER);
}
// 4 绑定 Controller
if (wasAttached) {
attachController();
}
}
}
可以看到这里主要的操作有两个步骤
- 解绑之前 Controller
- 解绑 Hierarchy
- 回调 Controller 的 onDetach
- 绑定新的 Controller
- 绑定 Hierarchy
- 回调 Controller 的 onAttach
这里我们主要 focus 一下新 Controller 的绑定过程
1. 绑定 DraweeHierarchy
PipelineDraweeController 的
public abstract class AbstractDraweeController<T, INFO> implements
DraweeController,
DeferredReleaser.Releasable,
GestureDetector.ClickListener {
/**
* Sets the hierarchy.
*
* <p>The controller should be detached when this method is called.
* @param hierarchy This must be an instance of {@link SettableDraweeHierarchy}
*/
@Override
public void setHierarchy(@Nullable DraweeHierarchy hierarchy) {
......
// 清空之前回调的数据
if (mIsRequestSubmitted) {
mDeferredReleaser.cancelDeferredRelease(this);
release();
}
// 清空之前的 DraweeHierarchy
if (mSettableDraweeHierarchy != null) {
mSettableDraweeHierarchy.setControllerOverlay(null);
mSettableDraweeHierarchy = null;
}
// 更新到成员变量 mSettableDraweeHierarchy 中
if (hierarchy != null) {
Preconditions.checkArgument(hierarchy instanceof SettableDraweeHierarchy);
mSettableDraweeHierarchy = (SettableDraweeHierarchy) hierarchy;
......
}
}
}
可以看到为 PipelineDraweeController 设置新的 Hierarchy 的过程主要是清空之前的数据之后将新的 Hierarchy 注入到成员变量
除此之之外没有做额外的工作, 接下来我们看看 onAttach 中做了些什么
2. 回调 onAttach
public abstract class AbstractDraweeController<T, INFO> implements
DraweeController,
DeferredReleaser.Releasable,
GestureDetector.ClickListener {
@Override
public void onAttach() {
......
mDeferredReleaser.cancelDeferredRelease(this);
mIsAttached = true;
if (!mIsRequestSubmitted) {
// 提交这个请求
submitRequest();
}
}
}
可以看到, 在绑定了 Hierarchy 之后, 会提交这个请求, 这便是图片加载的核心所在了, 下面我们看看它的实现
public abstract class AbstractDraweeController<T, INFO> implements
DraweeController,
DeferredReleaser.Releasable,
GestureDetector.ClickListener {
protected void submitRequest() {
// 1. 从缓存中直接获取当前 Controller 要加载的图片
final T closeableImage = getCachedImage();
if (closeableImage != null) {
mDataSource = null;
mIsRequestSubmitted = true;
mHasFetchFailed = false;
......
getControllerListener().onSubmit(mId, mCallerContext);
onImageLoadedFromCacheImmediately(mId, closeableImage);
// 回调图片加载成功
onNewResultInternal(mId, mDataSource, closeableImage, 1.0f, true, true);
return;
}
getControllerListener().onSubmit(mId, mCallerContext);
// 重置加载进度
mSettableDraweeHierarchy.setProgress(0, true);
mIsRequestSubmitted = true;
mHasFetchFailed = false;
// 2. 获取数据源
mDataSource = getDataSource();
final String id = mId;
final boolean wasImmediate = mDataSource.hasResult();
// 3. 构建观察者
final DataSubscriber<T> dataSubscriber =
new BaseDataSubscriber<T>() {
@Override
public void onNewResultImpl(DataSource<T> dataSource) {
// isFinished must be obtained before image, otherwise we might set intermediate result
// as final image.
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
T image = dataSource.getResult();
if (image != null) {
// 加载成功
onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
} else if (isFinished) {
// 加载失败
onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
}
}
@Override
public void onFailureImpl(DataSource<T> dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
@Override
public void onProgressUpdate(DataSource<T> dataSource) {
// 跟新加载进度
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
// 4. 为数据源添加一个观察者
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
}
}
这里我们就初步看到 Fresco 的图片加载动作了, 主要流程如下
- 尝试从缓存中获取数据, 若命中则直接返回
- 通过 getDataSource 获取数据源
- 构建这个数据源的观察者 DataSubscriber
- 为数据源订阅观察者, 数据源准备好之后便会通知观察者, 回调其中的方法
这里我们主要关注一下 getDataSource 是如何构建数据源的
public class PipelineDraweeController
extends AbstractDraweeController<CloseableReference<CloseableImage>, ImageInfo> {
@Override
protected DataSource<CloseableReference<CloseableImage>> getDataSource() {
......
// 直接通过 mDataSourceSupplier 获取 DataSource
return mDataSourceSupplier.get();
}
}
通过上面分析可知, get 方法最终会调用到 ImagePipeline.fetchDecodedImage, 下面看看它的具体实现
public class ImagePipeline {
public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage(
ImageRequest imageRequest,
Object callerContext,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit) {
try {
// 1. 创建数据生产者
Producer<CloseableReference<CloseableImage>> producerSequence =
mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
// 提交这个获取请求
return submitFetchRequest(
producerSequence,
imageRequest,
lowestPermittedRequestLevelOnSubmit,
callerContext);
} catch (Exception exception) {
......// 处理失败的情况
}
}
private <T> DataSource<CloseableReference<T>> submitFetchRequest(
Producer<CloseableReference<T>> producerSequence,
ImageRequest imageRequest,
ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit,
Object callerContext) {
final RequestListener requestListener = getRequestListenerForRequest(imageRequest);
try {
// 获取请求优先级
ImageRequest.RequestLevel lowestPermittedRequestLevel =
ImageRequest.RequestLevel.getMax(
imageRequest.getLowestPermittedRequestLevel(),
lowestPermittedRequestLevelOnSubmit);
// 2. 构建生产者上下文数据
SettableProducerContext settableProducerContext = new SettableProducerContext(
imageRequest,
generateUniqueFutureId(),
requestListener,
callerContext,
lowestPermittedRequestLevel,
/* isPrefetch */ false,
imageRequest.getProgressiveRenderingEnabled() ||
imageRequest.getMediaVariations() != null ||
!UriUtil.isNetworkUri(imageRequest.getSourceUri()),
imageRequest.getPriority());
// 3. 调用 CloseableProducerToDataSourceAdapter 的 create 方法, 创建 DataSource
return CloseableProducerToDataSourceAdapter.create(
// 生产者序列
producerSequence,
// 生产者上下文
settableProducerContext,
// 请求监听
requestListener);
} catch (Exception exception) {
... // 处理失败情况
}
}
}
可以看到 ImagePipeline 的构建过程, 主要有如下几个步骤
- 构建 Producer<CloseableReference
> producerSequence 数据生产者 - 构建 SettableProducerContext 生产者上下文
- 通过 CloseableProducerToDataSourceAdapter.create 将一个 Producer 通过 Adapter 的方式适配成 DataSource
这里我们主要关注生产者的构建和 DataSource 的创建
1) 创建数据生产者
public class ProducerSequenceFactory {
public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(
ImageRequest imageRequest) {
// 1. 获取最基础的图片解码生产者
Producer<CloseableReference<CloseableImage>> pipelineSequence =
getBasicDecodedImageSequence(imageRequest);
// 2. 若 imageRequest 的 Postprocessor 非空, 则对基础的 Producer 进行装饰, 增强其功能
if (imageRequest.getPostprocessor() != null) {
pipelineSequence = getPostprocessorSequence(pipelineSequence);
}
// 3. 若设置了需要在 mUseBitmapPrepareToDraw 标记位, 则再使用一层装饰, 增强这个功能
if (mUseBitmapPrepareToDraw) {
pipelineSequence = getBitmapPrepareSequence(pipelineSequence);
}
return pipelineSequence;
}
}
从这里可以看到 Fresco 是采用装饰器的方式对生产者的能力进行增强, 由于篇幅已经很长了, 生产者的具体实现就不再这里展开了, 感兴趣的同学可以先顺着这个思路深入探究
2) 将生产者适配成 DataSource
下面我们主要看看 CloseableProducerToDataSourceAdapter.create 是如何构建 DataSource 的
public class CloseableProducerToDataSourceAdapter<T>
extends AbstractProducerToDataSourceAdapter<CloseableReference<T>> {
public static <T> DataSource<CloseableReference<T>> create(
Producer<CloseableReference<T>> producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
// new 了这个对象
return new CloseableProducerToDataSourceAdapter<T>(
producer, settableProducerContext, listener);
}
private CloseableProducerToDataSourceAdapter(
Producer<CloseableReference<T>> producer,
SettableProducerContext settableProducerContext,
RequestListener listener) {
// 回调父类方法
super(producer, settableProducerContext, listener);
}
}
public abstract class AbstractProducerToDataSourceAdapter<T> extends AbstractDataSource<T>
implements HasImageRequest {
private final SettableProducerContext mSettableProducerContext;
private final RequestListener mRequestListener;
protected AbstractProducerToDataSourceAdapter(
Producer<T> producer,
SettableProducerContext settableProducerContext,
RequestListener requestListener) {
mSettableProducerContext = settableProducerContext;
mRequestListener = requestListener;
mRequestListener.onRequestStart(
settableProducerContext.getImageRequest(),
mSettableProducerContext.getCallerContext(),
mSettableProducerContext.getId(),
mSettableProducerContext.isPrefetch());
// 1. 创建 Consumer 用于接收生产后的数据
// 2. 调用 producer 的 produceResults 方法, 进行数据生产
producer.produceResults(createConsumer(), settableProducerContext);
}
private Consumer<T> createConsumer() {
return new BaseConsumer<T>() {
......
}
}
从这里可以看到 Fresco 的数据生产与接收是一个生产者与消费者的模型, DataSource 是对外提供的接口, 其内部由 Producer 和 Consumer 组成
三) 回顾
Drawee 的数据加载主要步骤如下
- PipelineDraweeController 创建
- 通过 PipelineDraweeControllerBuilderSupplier 获取 PipelineDraweeControllerBuilder
- 通过 PipelineDraweeControllerBuilder 构造 PipelineDraweeController 对象
- 构建 DataSource 提供器
- 最终由 ImagePipeline.fetchDecodedImage 获取到 ImageRequest 对应的 DataSource
- 交由 PipelineDraweeControllerFactory 工厂创建 PiplelineDrawee 对象
- 注入成员变量, 为可变参数赋初值
- 构建 DataSource 提供器
- 为 DraweeView 注入 Controller
- 绑定 DraweeHierarchy
- 回调 onAttach
- 通过 ImagePipeline.fetchDecodedImage 获取 DataSource
- 创建数据生产者 Producer, 使用装饰器对其功能进行增强
- 为生产者注入 Consumer, 生产的结果通过 Consumer 对外抛出
- 为 DataSource 注入观察者, 用于监听数据加载状态
- 通过 ImagePipeline.fetchDecodedImage 获取 DataSource
三. 生产者构建流程
public class ProducerSequenceFactory {
// 获取 Decode Image 的生产者序列
public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(
ImageRequest imageRequest) {
// 1. 获取图片解码生产序列
Producer<CloseableReference<CloseableImage>> pipelineSequence =
getBasicDecodedImageSequence(imageRequest);
// 2. 获取后处理序列
if (imageRequest.getPostprocessor() != null) {
pipelineSequence = getPostprocessorSequence(pipelineSequence);
}
// 3. 获取 Bitmap 准备序列
if (mUseBitmapPrepareToDraw) {
pipelineSequence = getBitmapPrepareSequence(pipelineSequence);
}
return pipelineSequence;
}
}
上面的代码即生产者序列的构建流程, 主要有如下的几个类型
- 获取基础图片解码序列
- 获取后处理序列
- 获取 Bitmap 准备序列
这里我们主要 focus 基础图片的解码序列的构建
public class ProducerSequenceFactory {
private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence(
ImageRequest imageRequest) {
try {
......
Uri uri = imageRequest.getSourceUri();
......
// 根据请求类型, 获取对应的生产序列
switch (imageRequest.getSourceUriType()) {
// 从网络获取数据资源的生产序列
case SOURCE_TYPE_NETWORK:
return getNetworkFetchSequence();
// 从本地视频文件获取资源的生产序列
case SOURCE_TYPE_LOCAL_VIDEO_FILE:
return getLocalVideoFileFetchSequence();
// 本地图片文件
case SOURCE_TYPE_LOCAL_IMAGE_FILE:
return getLocalImageFileFetchSequence();
// ContentUri
case SOURCE_TYPE_LOCAL_CONTENT:
if (MediaUtils.isVideo(mContentResolver.getType(uri))) {
return getLocalVideoFileFetchSequence();
}
return getLocalContentUriFetchSequence();
// asset 文件
case SOURCE_TYPE_LOCAL_ASSET:
return getLocalAssetFetchSequence();
// resource 文件
case SOURCE_TYPE_LOCAL_RESOURCE:
return getLocalResourceFetchSequence();
// Qualified 资源文件
case SOURCE_TYPE_QUALIFIED_RESOURCE:
return getQualifiedResourceFetchSequence();
// 从缓存中获取
case SOURCE_TYPE_DATA:
return getDataFetchSequence();
default:
throw new IllegalArgumentException(
"Unsupported uri scheme! Uri is: " + getShortenedUriString(uri));
}
}
......
}
}
getBasicDecodedImageSequence 主要是根据 ImageRequest 中的 URI 创建对应的生产序列, 这里我们选取流程最长的 getNetworkFetchSequence 来分析这一次构建流程
public class ProducerSequenceFactory {
@VisibleForTesting Producer<CloseableReference<CloseableImage>> mNetworkFetchSequence;
private synchronized Producer<CloseableReference<CloseableImage>> getNetworkFetchSequence() {
......
if (mNetworkFetchSequence == null) {
......
// 1. 调用 getCommonNetworkFetchToEncodedMemorySequence 构建生产序列
// 2. 调用 newBitmapCacheGetToDecodeSequence 构建最终的 mNetworkFetchSequence 序列
mNetworkFetchSequence =
newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
......
}
......
return mNetworkFetchSequence;
}
}
一) getCommonNetworkFetchToEncodedMemorySequence
public class ProducerSequenceFactory {
private Producer<EncodedImage> mCommonNetworkFetchToEncodedMemorySequence;
/** multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch. */
private synchronized Producer<EncodedImage> getCommonNetworkFetchToEncodedMemorySequence() {
......
if (mCommonNetworkFetchToEncodedMemorySequence == null) {
......
// 1. 创建 NetworkFetchProducer 生产者
// 2. 调用 newEncodedCacheMultiplexToTranscodeSequence 创建缓存相关生产序列
Producer<EncodedImage> inputProducer =
newEncodedCacheMultiplexToTranscodeSequence(
mProducerFactory.newNetworkFetchProducer(mNetworkFetcher));
// 3. 创建 AddImageTransformMetaDataProducer 生产者
mCommonNetworkFetchToEncodedMemorySequence =
ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer);
// 4. 创建 ResizeAndRotateProducer 生产者
mCommonNetworkFetchToEncodedMemorySequence =
mProducerFactory.newResizeAndRotateProducer(
mCommonNetworkFetchToEncodedMemorySequence,
mResizeAndRotateEnabledForNetwork && !mDownsampleEnabled,
mImageTranscoderFactory);
......
}
......
// 返回这个构建好的 mCommonNetworkFetchToEncodedMemorySequence
return mCommonNetworkFetchToEncodedMemorySequence;
}
private Producer<EncodedImage> newEncodedCacheMultiplexToTranscodeSequence(
Producer<EncodedImage> inputProducer) {
// 2.1 根据是否支持 Webp, 构建 Webp 的解码生产者
if (WebpSupportStatus.sIsWebpSupportRequired &&
(!mWebpSupportEnabled || WebpSupportStatus.sWebpBitmapFactory == null)) {
inputProducer = mProducerFactory.newWebpTranscodeProducer(inputProducer);
}
// 2.2 构建磁盘生产者序列
if (mDiskCacheEnabled) {
inputProducer = newDiskCacheSequence(inputProducer);
}
// 2.3 创建内存缓存生产者
EncodedMemoryCacheProducer encodedMemoryCacheProducer =
mProducerFactory.newEncodedMemoryCacheProducer(inputProducer);
// 2.4 创建解码缓存的 Key 的生产者
return mProducerFactory.newEncodedCacheKeyMultiplexProducer(encodedMemoryCacheProducer);
}
private Producer<EncodedImage> newDiskCacheSequence(Producer<EncodedImage> inputProducer) {
// 2.2.1 创建 DiskCacheWriteProducer
Producer<EncodedImage> cacheWriteProducer;
......
if (mPartialImageCachingEnabled) {
Producer<EncodedImage> partialDiskCacheProducer =
mProducerFactory.newPartialDiskCacheProducer(inputProducer);
cacheWriteProducer = mProducerFactory.newDiskCacheWriteProducer(partialDiskCacheProducer);
} else {
cacheWriteProducer = mProducerFactory.newDiskCacheWriteProducer(inputProducer);
}
// 2.2.2 创建 DiskCacheReadProducer
DiskCacheReadProducer result = mProducerFactory.newDiskCacheReadProducer(cacheWriteProducer);
......
return result;
}
}
可以看到 getCommonNetworkFetchToEncodedMemorySequence 中创建了非常多的生产者, 看似比较混乱, 其实还是比较清晰的, 主要如下
- 创建 NetworkFetchProducer 生产者
- 根据是否支持 Webp, 创建 Webp 的解码生产者 WebpTranscodeProducer
- 创建磁盘缓存生产序列
- 创建 DiskCacheWriteProducer
- 创建 DiskCacheReadProducer
- 创建编码数据的内存缓存序列
- 创建 EncodedMemoryCacheProducer
- 创建 EncodedCacheKeyMultiplexProducer
- 创建 AddImageTransformMetaDataProducer
- 创建 ResizeAndRotateProducer
二) newBitmapCacheGetToDecodeSequence
public class ProducerSequenceFactory {
private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToDecodeSequence(
Producer<EncodedImage> inputProducer) {
......
// 1. 创建 DecodeProducer 解码生产者
DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);
// 2. 创建 Bitmap 缓存生产序列
Producer<CloseableReference<CloseableImage>> result =
newBitmapCacheGetToBitmapCacheSequence(decodeProducer);
return result;
}
private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToBitmapCacheSequence(
Producer<CloseableReference<CloseableImage>> inputProducer) {
// 2.1 创建 BitmapMemoryCacheProducer
BitmapMemoryCacheProducer bitmapMemoryCacheProducer =
mProducerFactory.newBitmapMemoryCacheProducer(inputProducer);
// 2.2 创建 BitmapMemoryCacheKeyMultiplexProducer
BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer =
mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);
// 2.3 创建 ThreadHandoffProducer
ThreadHandoffProducer<CloseableReference<CloseableImage>> threadHandoffProducer =
mProducerFactory.newBackgroundThreadHandoffProducer(
bitmapKeyMultiplexProducer,
mThreadHandoffProducerQueue);
// 2.4 创建 BitmapMemoryCacheGetProducer 生产者
return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);
}
}
newBitmapCacheGetToDecodeSequence 主要是构建解码和 Bitmap 内存缓存相关的生产者
- 创建 DecodeProducer 解码生产者
- 创建 Bitmap 缓存生产者
- 创建 BitmapMemoryCacheProducer
- 创建 BitmapMemoryCacheKeyMultiplexProducer
- 创建 ThreadHandoffProducer
- 创建 BitmapMemoryCacheGetProducer 生产者
三) 回顾
一次请求所构建的生产者责任链序列如下
- 网络缓存相关
- NetworkFetchProducer: 从网络上获取数据源
- 转码服务
- WebpTranscodeProducer: 将 webp 转码为 jpeg/png
- 磁盘缓存
- DiskCacheWriteProducer: 将数据写入磁盘缓存
- DiskCacheReadProducer: 从磁盘缓存中读数据
- 编码内存缓存
- EncodedMemoryCacheProducer: 读/写 图片编码后数据的内存缓存
- EncodedCacheKeyMultiplexProducer: 合并相同的编码内存请求
- AddImageTransformMetaDataProducer: 获取图片的 MetaData
- ResizeAndRotateProducer: 图片的旋转与缩放
- DecodeProducer: 负责图片的解码
- Bitmap 内存缓存
- BitmapMemoryCacheProducer: 读/写 Bitmap 内存缓存
- BitmapMemoryCacheKeyMultiplexProducer: 合并相同的 Bitmap 内存缓存请求
- ThreadHandoffProducer: 线程切换
- BitmapMemoryCacheGetProducer: 读 Bitmap 内存缓存
总结
初始化
Fresco 的初始化流程主要如下
- 加载 Fresco 的 so 库
- 构建 ImagePipelineFactory 对后续对图像的编解码提供支持
- 初始化 Drawee
- 创建 PipelineDraweeControllerBuilderSupplier 用于提供 PipelineDraweeControllerBuilder 对象
- 持有 ImagePipeline 和 PipelineDraweeControllerFactory 两个非常重要的对象
- 为 SimpleDraweeView 注入 Supplier, 方便 SimpleDraweeView 构建 DraweeControllerBuilder.
- 创建 PipelineDraweeControllerBuilderSupplier 用于提供 PipelineDraweeControllerBuilder 对象
SimpleDraweeView 的创建
SimpleDraweeView 的创建流程如下
- 创建 DraweeHolder
- 持有 DraweeHierarchy
- 创建 GenericDraweeHierarchy
- RootDrawable
- RoundedDrawable
- FadeDrawable
- FadeDrawable
- 按压的 Drawable
- Overlay 的 Drawables
- 失败 Drawable: ScaleTypeDrawable
- 重试 Drawable: ScaleTypeDrawable
- 进度条 Drawable: maybe null
- 真实目标的 Drawable: ScaleTypeDrawable(提供 ScaleType 缩放能力)
- ForwardingDrawable (包装一下, 提供拓展空间)
- Drawable(用户设置的)
- ForwardingDrawable (包装一下, 提供拓展空间)
- 展位图 Drawable: ScaleTypeDrawable
- 背景 Drawable
- RoundedDrawable
- RootDrawable
- 将 GenericDraweeHierarchy 注入 Holder 中暂存
数据加载
Drawee 的数据加载主要步骤如下
- PipelineDraweeController 创建
- 通过 PipelineDraweeControllerBuilderSupplier 获取 PipelineDraweeControllerBuilder
- 通过 PipelineDraweeControllerBuilder 构造 PipelineDraweeController 对象
- 构建 DataSource 提供器
- 最终由 ImagePipeline.fetchDecodedImage 获取到 ImageRequest 对应的 DataSource
- 交由 PipelineDraweeControllerFactory 工厂创建 PiplelineDrawee 对象
- 注入成员变量, 为可变参数赋初值
- 构建 DataSource 提供器
- 为 DraweeView 注入 Controller
- 绑定 DraweeHierarchy
- 回调 onAttach
- 通过 ImagePipeline.fetchDecodedImage 获取 DataSource
- 创建数据生产者 Producer, 使用装饰器对其功能进行增强
- 为生产者注入 Consumer, 生产的结果通过 Consumer 对外抛出
- 为 DataSource 注入观察者, 用于监听数据加载状态
- 通过 ImagePipeline.fetchDecodedImage 获取 DataSource
生产责任链的构建
一次请求所构建的生产者序列如下
- 网络缓存相关
- NetworkFetchProducer: 从网络上获取数据源
- 转码服务
- WebpTranscodeProducer: 将 webp 转码为 jpeg/png
- 磁盘缓存
- DiskCacheWriteProducer: 将数据写入磁盘缓存
- DiskCacheReadProducer: 从磁盘缓存中读数据
- 编码内存缓存
- EncodedMemoryCacheProducer: 读/写 图片编码后数据的内存缓存
- EncodedCacheKeyMultiplexProducer: 合并相同的编码内存请求
- AddImageTransformMetaDataProducer: 获取图片的 MetaData
- ResizeAndRotateProducer: 图片的旋转与缩放
- DecodeProducer: 负责图片的解码
- Bitmap 内存缓存
- BitmapMemoryCacheProducer: 读/写 Bitmap 内存缓存
- BitmapMemoryCacheKeyMultiplexProducer: 合并相同的 Bitmap 内存缓存请求
- ThreadHandoffProducer: 线程切换
- BitmapMemoryCacheGetProducer: 读 Bitmap 内存缓存
结语
这里梳理了一遍 Fresco 的加载流程, 能够感受到 Facebook 的工程师设计功底的深厚, 这里简单的记录一下自己的阅读感受
从使用层面上来看
- Fresco
- 优势: 提供了 DraweeView, 其中的 Hierarchy 提供了非常丰富的层级, 能够应对绝大多数场景, 使用方便
- 劣势: 对控件进行二次包装存在一定的成本, 容易产生直接性的依赖
- Glide
- 优势: 与 View 没有直接依赖, 所有的操作最终会生成一个 Drawable 交付给 ImageView 进行最后的渲染, 便于封装
- 劣势: 由于对外提供的是链式调用的函数, 因此对于图片圆角等处理需要写额外的代码, 使用起来比 Fresco 稍有不便
从整体设计上来看
- Fresco
- 数据加载模块使用了生产者消费者模型构成责任链模式, 职责非常清晰, 是值得借鉴和学习的封装思路
- Glide
- 数据模块使用大量回调, 阅读难度高, 职责有些不够清晰, 有提升空间
这里关于每一个 Producer 的具体实现就不展开分析了, 感兴趣可以根据相关类名查阅