Fresco解析(DraweeView,DraweeHierarchy)

上一篇分析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的核心,流程也较为复杂,下篇分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值