上一篇分析SimpleDraweeView调用setController方法来显示图片, 接下来分析setController具体实现。按住Ctrl进入setController内部,看到此方法定义在DraweeView中,那就先分析DraweeView。
DraweeView
先看注释:
/*
* View that displays a {@link DraweeHierarchy}.
* Hierarchy should be set prior to using this view. See {@code setHierarchy}. Because creating a hierarchy is an expensive operation, it is recommended this be done once per view, typically near creation time.
* In order to display an image, controller has to be set. See {@code setController}.
* Although ImageView is subclassed instead of subclassing View directly, this class does not
* support ImageView's setImageXxx, setScaleType and similar methods. Extending ImageView is a short term solution in order to inherit some of its implementation (padding calculations, etc.).
* This class is likely to be converted to extend View directly in the future, so avoid using
* ImageView's methods and properties (T5856175).
* /
- DraweeView用来展示DraweeHierarchy。
- 使用DraweeView之前,要使用setHierarchy()方法为其提供一个DraweeHierarchy,创建DraweeHierarchy非常耗费资源,推荐在创建DraweeHierarchy的时候调用setHierarchy方法。
- 调用setController()为其提供一个DraweeController。
- 尽管DraweeView直接继承自ImageView,但是不支持ImageView的setImageXXX,setScaleType等类似的方法。Fresco继承ImageView只是一个短期方案,将来可能直接继承View所以避免使用ImageView的方法和属性。
看下DraweeView的继承关系
GenericDraweeView
GenericDraweeView的注释很简单:
DraweeView that creates GenericDraweeHierarchy based on XML attributes.
DraweeView 基于XML属性创建GenericDraweeHierarchy.
根据上一篇分析,在SimpleDraweeView加载的时候会调用GenericDraweeView的构造方法,然后调用GenericDraweeView的inflateHierarchy()方法,之前分析过这个方法主要是解析XML文件,生成一个Hierarchy对象,看详细代码:
private void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
Resources resources = context.getResources();
//把在XML布局中配置的属性 提取出来,例如:占位图,ScaleType,失败图片,重试图片 等等
...........................................
//将从XML文件中提取出来的配置 传入到GenericDraweeHierarchyBuilder中
...............................
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
//通过Builder构建一个DraweeHierarchy对象,调用DraweeView的setController 传入到了Controller中
setHierarchy(builder.build());
}
SimpleDraweeView
/**
* This view takes a uri as input and internally builds and sets a controller.
* This class must be statically initialized in order to be used. If you are using the Fresco
* image pipeline, use {@link com.facebook.drawee.backends.pipeline.Fresco#initialize} to do this.
*/
- SimpleDraweeView负责接收URI的参数,然后在内部构建一个Controller再调用setController
- SimpleDraweeView必须被初始化才能使用(也可以使用ImagePipeline来完成)
DraweeHierarchy
DraweeHierarchy也是一个接口,看注释:
/**
* Interface that represents a Drawee hierarchy.
* <p> A hierarchy assembles a tree of Drawables in order to form a dynamically changeable display.
* This is much more lightweight than the traditional Android way of nesting View objects.
* <p> Hierarchy details are hidden for the outside world. All that's visible is the top level
* drawable, which can be put into a view.
* <p> Example hierarchy:
* * o FadeDrawable (top level drawable)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o BitmapDrawable
* |
* +--o ScaleTypeDrawable
* |
* +--o BitmapDrawable
* */
- 为了动态改变显示的内容,将Drawee Hierarchy封装成了一个drawable的树状结构,这种方式比Android传统的View的嵌套方式更轻量级。
- Hierarchy的细节被最外层的Drawable覆盖,只有顶部的Drawable可以显示到View中。(举了一个Drawable树状结构的例子)
DraweeHierarchy接口只定义了一个方法,getTopLevelDrawable() 来获取drawable树最上层的drawable。
DraweeHierarchy的继承关系:
SettableDraweeHierarchy
SettableDraweeHierarchy也是一个接口,看注释:
/**
* Interface that represents a settable Drawee hierarchy. Hierarchy should display a placeholder
* image until the actual image is set. In case of a failure, hierarchy can choose to display
* a failure image.
* IMPORTANT: methods of this interface are to be used by controllers ONLY!
* Example hierarchy:
* o FadeDrawable (top level drawable)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o ColorDrawable (placeholder image)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o BitmapDrawable (failure image)
* |
* +--o ScaleTypeDrawable
* |
* +--o SettableDrawable
* |
* +--o BitmapDrawable (actual image)
* * SettableDraweeHierarchy in the given example has a FadeDrawable as its top level drawable.
* Top level drawable can be immediately put into view. Once the actual image is ready, it will
* be set to the hierarchy's SettableDrawable and fade animation between the placeholder and the
* actual image will be initiated. In case of failure, hierarchy will switch to failure image.
* All image branches are wrapped with ScaleType drawable which allows separate scale type to be applied on each.
*/
- SettableDraweeHierarchy代表的是可以设置的DraweeHierarchy的接口。
- DraweeHierarchy在真实图片显示之前应先显示一个占位图,如果显示图片失败DraweeHierarchy可以显示一张失败的图片。
- SettableDraweeHierarchy注释举了一个实例: FadeDrawable在最顶层,顶层的Drawable可以立刻显示到View中,一旦真实的图片准备好,就会设置将SettableDrawable设置上去,然后placeholder和真是图片之间的动画会开始执行。如果设置图片失败,DraweeHierarchy会切换到失败的图片。
- (重要)SettableDraweeHierarchy接口的所有方法只能被Controller调用。
SettableDraweeHierarchy是DraweeHierarchy接口的扩展,此接口提供了下列方法(只能在Controller中调用):
- reset(); 将hierarchy恢复成初始状态,之前通过setImageURI设置的图片将不会被再使用。
- setImage(Drawable drawable, boolean immediate, int progress); 真实图片成功加载,显示时调用此方法
- setProgress(int progress, boolean immediate); 更新进度
- setFailure(Throwable throwable);真实图片加载失败
- setRetry(Throwable throwable);设置重试
- setControllerOverlay(Drawable drawable);
GenericDraweeHierarchy
从继承关系图看GenericDraweeHierarchy是DraweeHierarchy接口的具体实现类。
/**
* A SettableDraweeHierarchy that displays placeholder image until the actual image is set.
* If provided, failure image will be used in case of failure (placeholder otherwise).
* If provided, retry image will be used in case of failure when retrying is enabled.
* If provided, progressbar will be displayed until fully loaded.
* Each image can be displayed with a different scale type (or no scaling at all).
* Fading between the layers is supported.
* <p>
* <p>
* Example hierarchy with placeholder, retry, failure and one actual image:
* <pre>
* o FadeDrawable (top level drawable)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o Drawable (placeholder image)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o SettableDrawable
* | |
* | +--o Drawable (actual image)
* |
* +--o ScaleTypeDrawable
* | |
* | +--o Drawable (retry image)
* |
* +--o ScaleTypeDrawable
* |
* +--o Drawable (failure image)
* </pre>
* <p>
* <p>
* Note:
* - ScaleType and Matrix transformations will be added only if specified. If both are unspecified,
* then the branch for that image will be attached directly.
* - It is not permitted to set both ScaleType transformation and Matrix transformation for the
* same image.
* - A Matrix transformation is only supported for actual image.
* - All branches (placeholder, failure, retry, actual image, progressBar) are optional.
* If some branch is not specified it won't be created. The exception is placeholder branch,
* which will, if not specified, be created with a transparent drawable.
* - If overlays and/or backgrounds are specified, they are added to the same fade drawable, and
* are always displayed.
* - Instance of some drawable should be used by only one DH. If more than one DH is being built
* with the same builder, different drawable instances must be specified for each DH.
*/
大概的翻译:
* 真实图片显示之前,会显示placeHolder
* 加载失败时,如果设置了失败的图片则会显示,否则显示placeHolder
* 设置了progressbar时会在真实图片显示前显示
* 同一图片不允许同时设置Matrix和ScaleType属性
* Drawable树的各个分支是可选的,如果一个分支没有指定,会创建一个透明的drawable
上面分析GenericDraweeView的inflateHierarchy()方法将XML中的属性解析出来传入到了GenericDraweeHierarchyBuilder中,然后调用GenericDraweeHierarchyBuilder.build方法返回GenericDraweeHierarchy对象
public GenericDraweeHierarchy build() {
validate();
return new GenericDraweeHierarchy(this);
}
可以看到build方法调用了GenericDraweeHierarchy的构造方法。GenericDraweeHierarchy将XML文件中设置的属性对应的drawable保存在Drawable数组中,然后传入到了FadeDrawable中。
GenericDraweeHierarchy(GenericDraweeHierarchyBuilder builder) {
//.....................
//将Drawable保存到layers数组中
Drawable[] layers = new Drawable[numLayers];
if (numBackgrounds > 0) {
int index = 0;
for (Drawable background : builder.getBackgrounds()) {
layers[backgroundsIndex + index++] = background;
}
}
if (mPlaceholderImageIndex >= 0) {
layers[mPlaceholderImageIndex] = placeholderImageBranch;
}
if (mActualImageIndex >= 0) {
layers[mActualImageIndex] = actualImageBranch;
}
if (mProgressBarImageIndex >= 0) {
layers[mProgressBarImageIndex] = progressBarImageBranch;
}
if (mRetryImageIndex >= 0) {
layers[mRetryImageIndex] = retryImageBranch;
}
if (mFailureImageIndex >= 0) {
layers[mFailureImageIndex] = failureImageBranch;
}
//................
//将layers传到了FadeDrawable
mFadeDrawable = new RootFadeDrawable(layers);
}
DraweeHierarchy到这里就分析完了。
总结:
DraweeHierarchy中定义了一个drawable的树状结构,来组织和维护最终绘制和呈现的drawable对象,相当于MVC中的M。
DraweeView:继承View负责最终的显示,相当于MVC中的V。
DraweeController:是整个MVC的核心,流程也较为复杂,下篇分析。