前言
在正式开始分析之前,还是看一下DraweeHierarchy
的继承体系,做到心中有数。
看三个类的命名好像也只有SettableDraweeHierarchy
可以猜出来一些 – 可设置的层次结构。
而GenericDraweeHierarchy
你是不是哪里眼熟?没错,在GnericDraweeView
的inflateHierarchy()
的方法中,使用GenericDraweeHierarchyBuilder
构建出了一个DraweeHierarchy
的实例对象。
值得一提的是,DraweeHierarchy
的主要职责是提供可显示的图片,也就是Draweable
,而在Fresco中,默认定义了众多的Drawable
类,并在GenericDraweeHierarchy
的得到了充分的使用。
由于Drawable
体系知识我还没有研究,就先把Fresco自定义的Drawable
的体系脉络先梳理一下,以便混个眼熟。
ArrayDrawable-FadeDrawable
看一下ArrayDrawable
类的注释,可以知道:
- 这个Drawable包含其他的显示元素数组(层),并且都是以数组顺序绘制的,因此,元素数组的最大值(最末尾元素)将被绘制在顶部。
- 这个Drawable类似Android的
LayerDrawable
类,但是LayerDrawable
并不支持动态添加和移除图层。
简单明了,继续看一下FaseDrawable
类的注释:
- 可以使指定的图层逐渐消失
- 支持任意数量的图像;有五种不同的方式让图层逐渐消失。
- fadeInLayout:淡入指定的图层直到完全显示
- fadeOutLayout:淡出指定的图层直到完全透明
- fadeOutAllLayers:淡出所有的图层直到完全透明
- fadeToLayer:淡入指定的图层直到完全显示,同时淡出其他图层直到完全透明。
- fadeUpToLayer:淡入一个图层的集合到指定的图层并让指定的图层完全显示,同时淡出其他的图层至完全透明。
ProgressBarDrawable
- 基于
level
的值,显示一个进度条。
ForwardingDrawable体系
先看一下ForwardingDrawable
类的注释:
- 目标是代理drawable的功能到一个内部实例。
例如GenericDraweeHierarchy
中的RootDrawable
内部类。
正文
与前一篇文章不同,这次分析DraweeHierarchy
按照从上至下的顺序来。
DraweeHierarchy
DraweeeHierarchy
是一个接口,同时接口中也只有一个getTopLevelDraweable()
方法,想要了解其中暗含了那些意图,只能从注释入手。
- 为了可以动态改变显示的图像,
DraweeHierarchy
被组装成一个树状。 - 树状的层级比Android传统的嵌套视图,更加轻便。
- 树状层级的细节被隐藏,外界无法看到。所有的可见的图像,都是最顶级Drawable。
当然,这样子你可能会更清晰一些。
FaseDraweable
作为顶层图像,隐藏了其与的细节。
SettableDraweeHierarchy
看一下接口注释,我们能了解如下信息:
SettableDraweeHierarchy
接口代表可设置的层级结构。直到实际的图片被显示之前,它应该显示一张占位图;如果加载失败了,层级结构应该可以选择一张失败的图片用于显示。- 这些方法只能被Controller所调用。
此外,本接口还提供了如下方法:
- 图像可以被重置
- 图像可以设置进度
- 设置失败
- 设置重试
- 设置controllerOverlay
为了便于理解,还是给出层级结构的两种不同的表示方式。
GenericDraweeHierarchy
作为抽象接口的实现类,无非就是在原本抽象特性的基础上,又增加了一些其他的特性。
通过类注释,来粗略的看一下本类都做了些什么。
- 一个可设置的层级结构在成功显示实际图片前,会一直显示占位图。
- 如果提供了失败的图片,失败的图片将会被用于失败的情况下。
- 如果提供了重试的图片,重试的图片将会被用于失败并且重试可用的情况下。
- 如果提供了进度条,进度条会被一直显示直至加载完毕。
这样,层次结构就好像下面这个样子,从上至下依次执行状态:
分析完了基本脉络,接下来看看具体的代码是怎么做的。想实例化GnericDraweeHierarchy
类,必须要走构造方法,不过估计看到庞大的构造方法你就会眼晕。同时,想要构造方法必须要传入GenericDraweeHierarchyBuilder
的一个实例。
GenericDraweeHierarchy(GenericDraweeHierarchyBuilder builder) {
// ... 省略N行,构造GenericDraweeHierarchy的代码。
}
在构造方法上按ALT+F7
,看看在哪里调用了它。结果发现只有在GenericDraweeHierarchyBuilder
的build()
方法中被调用了。
public GenericDraweeHierarchy build() {
validate();
return new GenericDraweeHierarchy(this);
}
根据前一篇博客的分析,可以知道,在解析XML属性时,实例化了GenericDraweeHierarchyBuild
类,并使用建造者模式,构建出了GenericDraweeHierarchy
的实例对象。这样,这两端DraweeHierarchy
和DraweeView
就被我们串联起来了。
再回到GenericDraweeHierarchy
类的构造方法中,其实内部做的操作就是上图的映射,就是更加代码化了:
- 使用
numLayers
记录层级总数,每创建一个分子就+1。 - 创建占位图分支,如果用户未自定义,给一个透明的占位图;该分支是否需要圆角效果;该分支是否需要包裹缩放效果。此处的
waybeWrapWithScaleType()
的是包装设计模式的应用。 - 创建实例图像分支,默认给一个透明图;该分支是否需要缩放效果;是否需要Matrix效果;设置颜色过滤器;
- 创建进度条分支,判断该分支是否需要缩放效果;
- 创建重试分支,判断该分支是否需要缩放效果;
- 创建失败分支,判断该分支是否需要缩放效果;
- 创建覆盖层分支
- 根据层级总数,创建一个Drawable数组,并将填入对应的分支。随后使用该数组构造一个
FadeDrwable
类的实例(这个前文提过)。判断是否需要对FadeDrawable
的实例应用圆角效果。最后,使用最后的Drawable构造一个RootDrawable
的实例,并作为最顶层的图像(mTopLevelDrawable
),其中RootDrawable
是ForwardingDrawable
的子类,起到了代理作用。
就简单来说,将各种场景的Drawable放入一个数组中,并包装成FadeDrawable
以便在各种场景间切换,并根据其构造一个代理对象,以便添加一些需求。
一图胜千言,希望我画的图各位能看懂:O(∩_∩)O哈哈~
最后
DraweeHierarchy的体系分析就基本完成了,如果觉得对您有帮助,多多留言哦。
github:https://github.com/biezhihua