Fresco 源码的整体分析 —— 整体架构分析

本文详细分析了Fresco图片加载框架的整体架构,包括DraweeView、DraweeHierachy和DraweeController的角色及其相互关系。Fresco通过DataSource控制ProducerSequence发起图片加载流程,实现内存管理和自定义显示功能。文章还介绍了Fresco的模块组成,如UI层、数据加载和Producer的组合,揭示了其强大的图片处理能力。
摘要由CSDN通过智能技术生成

Fresco 是我们项目中图片加载专用框架。虽然我不是负责 Fresco 框架,但是由本人负责组里的图片加载浏览等工作,因此了解 Fresco 的源码有助于我今后的工作,也可以学习 Fresco 的源码设计精髓。

由于 Fresco 源码比较多,仅凭一篇文章是无法将其说清楚的,因此会当做一个系列,详细介绍 Fresco 源码。本系列文章也会参考网上关于 Fresco 源码解析的文章,尽可能准确的去描述 Fresco 的实现原理,如有错误之处欢迎指出,欢迎交流学习。

Fresco 是一个强大的图片加载组件。使用它之后,你不需要再去关心图片的加载和显示这些繁琐的事情! 支持 Android 2.3 及以后的版本。如果需要了解 Fresco 的使用可以访问 Fresco 使用文档 。

Fresco是一个功能完善的图片加载框架,在Android开发中有着广泛的应用,那么它作为一个图片加载框架,有哪些特色让它备受推崇呢?

完善的内存管理功能,减少图片对内存的占用,即便在低端机器上也有着不错的表现。

自定义图片加载的过程,可以先显示低清晰度图片或者缩略图,加载完成后再显示高清图,可以在加载的时候缩放和旋转图片。

自定义图片绘制的过程,可以自定义谷中焦点、圆角图、占位图、overlay、进图条。

渐进式显示图片。

支持Gif。

支持Webp。


Fresco 的组成结构还是比较清晰的,大致如下图所示:

其实这两张图来自不同的文章,但是我觉得两者的分层实际上基本是一样的。只是一个比较概括,一个比价具体,将两者摆在一起,更有助于大家去理解其实现细节。当然除了 UI 和加载显示部分外,还有 Gif,动态图片等内容,以及对应图片解码编码逻辑等。这部分不打算去讲解,因为这部分虽然也是源码很重要的一部分,但是这部分需要相关专业知识才好说明白,此外且涉及到 C++ 代码。

下面结合代码分别解释一下上面各模块的作用以及大概的工作原理。

DraweeView

它继承自 ImageView,是 Fresco 加载图片各个阶段过程中图片显示的载体,比如在加载图片过程中它显示的是占位图、在加载成功时切换为目标图片。不过后续官方可能不再让这个类继承 ImageView,所以该类并不支持 ImageView 的 setImageXxx, setScaleType 以及其他类似的方法。目前 DraweeView 与 ImageView 唯一的交集是:它利用 ImageView 来显示 Drawable :

复制代码
//DraweeView.setController()
public void setController(@Nullable DraweeController draweeController) {
mDraweeHolder.setController(draweeController);
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable()); //super 就是 ImageView
}

//DraweeHolder.getTopLevelDrawable()
public @Nullable Drawable getTopLevelDrawable() {
return mHierarchy == null ? null : mHierarchy.getTopLevelDrawable(); // mHierarchy 是 DraweeHierachy,
}
复制代码
DraweeView.setController() 会在 Fresco 加载图片时会调用。其实在这里可以看出 Fresco 的图片显示原理是 : 利用 ImageView 显示DraweeHierachy 的 TopLevelDrawable。上面这段代码引出了 UI 层中另外两个关键类: DraweeHolder 和 DraweeHierachy。

DraweeHierachy

可以说它是 Fresco 图片显示的实现者。它的输出是 Drawable,这个 Drawable 会被 DraweeView 拿来显示(上面已经说了)。它内部有多个 Drawable,当前显示在 DraweeView 的 Drawable 叫做 TopLevelDrawable。在不同的图片加载阶段,TopLevelDrawable 是不同的(比如加载过程中是 placeholder,加载完成是目标图片)。具体的 Drawable 切换逻辑是由它来具体实现的。

它是由 DraweeController 直接持有的,因此对于不同图片显示的切换操作具体是由 DraweeController 来直接操作的。

DraweeHolder

可以把它理解为 DraweeView、DraweeHierachy 和 DraweeController 这 3 个类之间的粘合剂, DraweeView 并不直接和 DraweeController 和 DraweeHierachy 直接接触,所有的操作都是通过它传过去。这样,后续将 DraweeView 的父类改为 View,也不会影响到其他类。DraweeView 作为 View 可以感知点击和生命周期,通过 DraweeHolder 来控制其他两个类的操作。

想想如果是你,你会抽出 DraweeHolder 这样一个类吗?实际上,这里对我们平时开发也是有所借鉴,严格控制每一个类之间的关系,可以引入一些一些中间类,让类与类之间的关系耦合度降低,方便日后迭代。

具体引用关系如下图:

它的主要功能是: 接收 DraweeView 的图片加载请求,控制 ProducerSequence 发起图片加载和处理流程,监听 ProducerSequence 加载过程中的事件(失败、完成等),并更新最新的 Drawable 到 DraweeHierachy。

DraweeController 的构造逻辑

在 Fresco 中 DraweeController 是通过 PipelineDraweeControllerBuilderSupplier 获取的。Fresco在初始化时会调用下面的代码:

// Fresco.java
private static void initializeDrawee(Context context, @Nullable DraweeConfig draweeConfig) {
sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context, draweeConfig);
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}
sDraweeControllerBuilderSupplier 是静态变量,也就是说其在只会初始一次。所有的 DraweeController 都是通过调用 sDraweecontrollerbuildersupplier.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值