4. Fresco的内容

为了方便学习,我们先从使用结合官方的文档来分析

4.1 Fresco客户端的使用##

在使用Fresco的使用,我们直接使用的是SimpleDraweeView这个类,然后在Activity或者Fragment中使用findViewById,然后便调用SimpleDraweeView.setImageUri(),这个方法,便直接可以加载图片,那么在这之间到底是怎么做的呢?结果打开SimpleDraweeView这个类,发现其继承体系,又发现中间有其他一些类,如果只是硬着头皮看代码,我们也会发现其中的逻辑,但是通过官方文档的介绍,我们会降低分析的时间花销

官方关于SimpleDraweeView的介绍

4.1.1 Drawees

rawees 负责图片的呈现,包含几个组件,有点像MVC模式

4.1.2 DraweeView(Viewer)

继承于 View, 负责图片的显示。

4.1.3 DraweeHierarchy(Model)

DraweeHierarchy 用于组织和维护最终绘制和呈现的Drawable对象,相当于MVC中的M。

4.1.4 DraweeController(Controller)

DraweeController 负责和 image loader 交互(默认是Fresco中 image pipeline),可以创建一个这个类的实例,来实现对所要显示的图片做更多的控制

4.1.5 DraweeView(Viewer)-DraweeHierarchy(Model)-DraweeController(Controller)的代码体现

了解通用的MVC模式,便知道Model负责的是持有数据,Viewer用于展示数据,Controller用于控制数据的逻辑,即核心的控制逻辑位于Controller中

MVC的示意图:

这个只是通用的MVC示意图,那么在Drawees中是如何体现呢:

在查看三者的关系时,我们从Viewer入手,在查看SimpleDraweeView,先看其继承体系

4.1.5.1 视图层DraweeView继承体系及各个类的作用

DraweeView

--| GenericDraweeView

------| SimpleDraweeView

DraweeView (Viewer)

获取和设置Hierarchy+Controller,DraweeView的相关信息在DraweeHolder中

DraweeHolder是一个辅助的类,解耦的设计方式,将需要设置以及传递控制的信息,全部交给DrawHolder来实现

GenericDraweeView

解析在xml中设置的属性

SimpleDraweeView

  1. 从外界设置ConrolllerBuilderSupplier
  2. 可以设置ImageUri

核心的业务逻辑位于DraweeView中

在控件初始化时,初始化了一个DraweeHolder

DraweeView的初始化源码

  private DraweeHolder<DH> mDraweeHolder;

  public DraweeView(Context context) {
super(context);
init(context);
} public DraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
} public DraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
} //---init中创建了一个DraweeHolder
private void init(Context context) {
mDraweeHolder = DraweeHolder.create(null, context);
}

再查看剩余的DraweeView的程序,发现其均将只是将相关事件传递给DraweeHolder,这是一种解耦的设计方式,以后就是不采用DraweeView,采用其他的方式,照样可以使用这套逻辑

DraweeView的剩余源码

查看完DraweeView的源码后,再查看其子类的源码,刚才已经提到,GenericDraweeView解析在xml中设置的属性

  public void setHierarchy(DH hierarchy) {
mDraweeHolder.setHierarchy(hierarchy);
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
} public DH getHierarchy() {
return mDraweeHolder.getHierarchy();
} public boolean hasHierarchy() {
return mDraweeHolder.hasHierarchy();
} @Nullable public Drawable getTopLevelDrawable() {
return mDraweeHolder.getTopLevelDrawable();
} public void setController(@Nullable DraweeController draweeController) {
mDraweeHolder.setController(draweeController);
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
} @Nullable public DraweeController getController() {
return mDraweeHolder.getController();
} public boolean hasController() {
return mDraweeHolder.getController() != null;
} @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mDraweeHolder.onAttach();
} @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mDraweeHolder.onDetach();
} @Override
public void onStartTemporaryDetach() {
super.onStartTemporaryDetach();
mDraweeHolder.onDetach();
} @Override
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
mDraweeHolder.onAttach();
} @Override
public boolean onTouchEvent(MotionEvent event) {
if (mDraweeHolder.onTouchEvent(event)) {
return true;
}
return super.onTouchEvent(event);
} @Override
@Deprecated
public void setImageDrawable(Drawable drawable) {
mDraweeHolder.setController(null);
super.setImageDrawable(drawable);
} @Override
@Deprecated
public void setImageBitmap(Bitmap bm) {
mDraweeHolder.setController(null);
super.setImageBitmap(bm);
} @Override
@Deprecated
public void setImageResource(int resId) {
mDraweeHolder.setController(null);
super.setImageResource(resId);
} @Override
@Deprecated
public void setImageURI(Uri uri) {
mDraweeHolder.setController(null);
super.setImageURI(uri);
}

GenericDraweeView构造的源码

构造的源码,分为两种,一种是从外界直接设置GenericDraweeHierarchy,另外一种是普通的xml中直接生成的GenericDraweeView,其实都是在自身设置了一个hierarchy,设置给了DraweeHolder,并且直接设置自身显示的view,获取的是DraweeHolder的topDrawable,这个DraweeHolder的getTopDrawable(),其实还是获取的GenericDraweeHierarchy的getTopDrawable()

public class GenericDraweeView extends DraweeView<GenericDraweeHierarchy> {

  private float mAspectRatio = 0;
private final AspectRatioMeasure.Spec mMeasureSpec = new AspectRatioMeasure.Spec(); public GenericDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context);
setHierarchy(hierarchy);
} public GenericDraweeView(Context context) {
super(context);
inflateHierarchy(context, null);
} public GenericDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
inflateHierarchy(context, attrs);
} public GenericDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflateHierarchy(context, attrs);
}
}

inflateHierarchy()的源码

在inflater的过程中,使用了构造者模式,构造者模式,一般适用于类的属性比较多,并且需要链式书写,在安卓的使用中,AlertDialog中也是使用了构造者模式,虽然模式很好用,但是写起来比较费劲,因为感觉好多东西感觉都是重复的

 private void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
......
int fadeDuration = GenericDraweeHierarchyBuilder.DEFAULT_FADE_DURATION;
// images & scale types defaults
int placeholderId = 0;
......
if (attrs != null) {
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.GenericDraweeView);
try {
// fade duration
fadeDuration = gdhAttrs.getInt(
R.styleable.GenericDraweeView_fadeDuration,
fadeDuration);
//----解析xml中设置的各个属性
.......
}
finally {
gdhAttrs.recycle();
}
} GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
// set fade duration
builder.setFadeDuration(fadeDuration);
// set images & scale types
if (placeholderId > 0) {
builder.setPlaceholderImage(resources.getDrawable(placeholderId), placeholderScaleType);
}
//---将解析出来的xml属性,设置给builder中的相关属性
......
setHierarchy(builder.build());
}

SimpleDraweeView的源码分析

分析方式同上,先查看构造函数,然后看其他方法,

构造方法方法,同样是两种方法,一种是支持从类中直接创建的,另外一种是从xml中创建出来的,在这两种方式中,都是先调用的父类的构造方法,然后在init中初始化了一个SimpleDraweeControllerBuilder

  private SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder;

  public SimpleDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
super(context, hierarchy);
init();
} public SimpleDraweeView(Context context) {
super(context);
init();
} public SimpleDraweeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} public SimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
} private void init() {
if (isInEditMode()) {
return;
}
Preconditions.checkNotNull(
sDraweeControllerBuilderSupplier,
"SimpleDraweeView was not initialized!");
mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get();
}

在init方法中,用到了一个Preconditions.checkNotNull的方法(这个是google自己提供的java的扩展包,这个包建议大家还是到网上查找相关介绍,因为功能比较强大。),另外,既然在这里都已经判空,那么sDraweeControllerBuilderSupplier肯定是要提前初始化的,在类中查看初始化的位置,发现位于静态的初始化方法中,至于何时调用这个方法,提前告诉大家,是在我们写Fresco.init()的方法,便已经初始化好了的,这就是为什么我们可以轻松的使用这个SimpleDraweeView了

private static Supplier<? extends SimpleDraweeControllerBuilder> sDraweeControllerBuilderSupplier;

  /** Initializes {@link SimpleDraweeView} with supplier of Drawee controller builders. */
public static void initialize(
Supplier<? extends SimpleDraweeControllerBuilder> draweeControllerBuilderSupplier) {
sDraweeControllerBuilderSupplier = draweeControllerBuilderSupplier;
}

SimpleDraweeView的面向用户方法的分析

这个是面向UI层开放的接口setImageUri(),下面我们查看其源码,发现其构造了一个DraweeController,然后设置给了SimpleDraweeView而已,同样,这里使用的是构造者模式

/**

* Displays an image given by the uri.

*

* @param uri uri of the image

* @param callerContext caller context

*/

public void setImageURI(Uri uri, @Nullable Object callerContext) {

DraweeController controller = mSimpleDraweeControllerBuilder

.setCallerContext(callerContext)

.setUri(uri)

.setOldController(getController())

.build();

setController(controller);

}

下篇我们要分析DraweeHierachy和DraweeController 链接地址:(http://www.cnblogs.com/pandapan/p/4644195.html)

安卓源码分析群: Android源码分析QQ1群号:164812238

Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeView的分析的更多相关文章

  1. Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析

    4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用 DraweeHierachy (I) --| SettableDraweeHierarchy (I) ------| Gen ...

  2. Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通

    4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...

  3. Fresco 源码分析 —— 整体架构

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

  4. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  5. Fresco 源码分析(序)

    1. 为什么要写这个分析的博客 其实关于Fresco的相关内容,大家上网搜索,一般可以找到一大推,但是为什么我还要写关于这个的呢,因为在网上搜索中文和英文的关于fresco的相关知识时,大家只是潜在的 ...

  6. Fresco源码解析 - DataSource怎样存储数据

    Fresco源码解析 - DataSource怎样存储数据 datasource是一个独立的 package,与FB导入的guava包都在同一个工程内 - fbcore. datasource的类关系 ...

  7. Fresco源码解析 - 创建一个ImagePipeline(一)

    在Fresco源码解析 - 初始化过程分析章节中, 我们分析了Fresco的初始化过程,两个initialize方法中都用到了 ImagePipelineFactory类. ImagePipeline ...

  8. Netty 源码解析(五): Netty 的线程池分析

    今天是猿灯塔“365篇原创计划”第五篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel Netty ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  10. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

随机推荐

  1. 优秀大数据GitHub项目一览

    http://blog.csdn.net/yaoxtao/article/details/50540485 优秀大数据GitHub项目一览 VMware CEO Pat Gelsinger曾说: 数据 ...

  2. c# 闭包 小例

    class Program { static void fnnn() { string[] k = new string[] { "x", "y", " ...

  3. js校验表单后提交表单的三种方法总结

    第一种: 复制代码 代码如下: <script type="text/javascript">         function check(form) { if(fo ...

  4. Assembly文件被锁定

    使用 Assembly.LoadFile 加载程序集后 ,被加载的文件就会被锁定,之后就不能对其执行转移.删除等操作 为了解决次问题,我们可以先读取成字节流,然后转换成Assembly.代码如下:复制 ...

  5. C#设计模式(3):抽象工厂模式(Abstract Factory)(转载)

    概述 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来 ...

  6. Hello world,Hello 2014,Bye 2013

    序 想要写点什么的时候发现不知道写什么了,用一句话来总结2013的话,就是2013是既熟悉又陌生的一年,熟悉是同样的开发工作,陌生是从河南到北京的环境改变,当时大学的卧谈会,谈论毕业了要做什么,想要在 ...

  7. win7 vmware 无法使用usb

    只有在win7下才会有这个问题,在xp下没有. 原因是: win7的主机上禁用了vmare usb arbitration(仲裁) service. 在主机上启用这个服务 重启即可. 如果无法启用vm ...

  8. 最长公共子序列(LCS)

    简单的DP. f[i][j]表示序列a中前i个中,序列b中前b个中,组成的最长公共子序列的长度. DP方程: if(a[i-1]==b[j-1]) f[i][j]=f[i-1][j-1]+1;  el ...

  9. javascript trigger触发事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. PHP程序员,因该养成 7 个面向对象的好习惯

    在 PHP 编程早期,PHP 代码在本质上是限于面向过程的.过程代码 的特征在于使用过程构建应用程序块.过程通过允许过程之间的调用提供某种程度的重用. 但是,没有面向对象的语言构造,程序员仍然可以把 ...