Android图片加载框架Fresco分析(四)

Fresco的Model层设计

上回讲到fresco的controller层,主要涉及到的是设置请求(ImageRequest)设置动画等等。下面讲述一下fresco的第三层次,Hierarchy层。

在SimpleDraweeView的最上层DraweeView中,有一个setHierarchy(),即开发者如果需要自己定义hierarchy的话,可以使用这个方法。而如果不用自定义的话。在DraweeView的子类GenericDraweeView的构造函数中便有已经设置好的hierarchy。同样的,hierarchy也需要一个builder(GenericDraweeHierarchyBuilder)才可以创建(fresco中builder模式随处可见)。是否还记得在xml中使用SimpleDraweeView时候设置的xml各种属性?这些属性在这里才真正用到。

Android快速多渠道打包方法

1.首先需要的是Python开发环境

去python官网https://www.python.org/downloads/下载最新版python3 双击安装,配置path环境变量,把python安装的目录添加进去。

2.需要使用的文件

必备文件:info文件夹\channel.txt和MultiChannelBuildTool.py

其余文件:其余文件有些是在打包的过程中会自动生成,如info文件夹/ temp.txt和包含有多渠道的app集合文件夹MutilChannel_*,这些文件在打包之前都要删除,附赠一个还有MD5校验工具。

注意:info文件夹和channel.txt如果没有可以自己新建起来,全部都是小写。
打包之前需要把MutilChannel_*文件夹和temp.txt都删除。
MultiChannelBuildTool.py的MD5为7A07C15C9B26881276CEC99C7D19DB34
每次打包之前都应该用MD5校验工具查看下,防止被人修改。

Android图片加载框架Fresco分析(三)

Fresco的Controller层设计

经过之前的分析,已经知道DraweeView的显示是需要controller层与hierarchy层接洽的。

每个view都有一个controller来控制。我们还是从源码来分析一下。

上次说道,SimpleDraweeView需要Fresco类在初始化方法中设置一个controller。其实这个controller便是PipelineDraweeControllerBuilderSupplier类提供的对象。

private static void initializeDrawee(Context context) {
  sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
  SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}

以上这些都是针对SimpleDraweeView由Fresco设置默认Controller,并无法自己定义。如果用户非要自己定义该怎么办呢?开发者也给我们提供了一个方法,这个方法也是在Fresco这个类中的newDraweeControllerBuilder()方法。我们先说fresco是如何使用自定义controller来协调View和Model层的。而且默认的配置也是facebook所推荐使用的。

读书:《程序员的思维修炼》

最近在读这本书,名字叫做《程序员的思维修炼:开发认知潜能的九堂课》。作者以让读者提高开发效率作为开始,分别从九个方面讲解了作为一个程序员(非程序员也一样)该如何锻炼自己的思想。

书中首先讲述了我们的工作基本上就是要从一个新生慢慢演变成一个专家。新手和专家之间的区别是什么呢,新手主要通过规范来工作,而专家通过感觉和灵感来工作,而这种感觉往往又是很准确的。书中也解释了该如何从一个新手变成一个专家。

接着对大脑进行了分析,得出大脑主要可以分成两种工作方式。R型和L型。R型的人注重整体,情感,灵感等更有艺术性的方面,主要是右脑。而L型则侧重于某个,单独,规律性的方面,主要是左脑。

了解了L型和R型大脑之后,就要开始训练右脑,主要的方法便是开始感官输入。让L型和R型相互合作,一起促进大脑的运作。

Android图片加载框架Fresco分析(二)

Fresco的View层设计

Fresco的view层较为简单,主要有三个view,DraweeView <– GenericDraweeView <– SimpleDraweeView,这便是View层控件的继承关系。在这三个view中,如果需要简单使用的话,可以直接使用SimpleDraweeView,如果要自定义View的话也可以继承上层的两个view。GenericDraweeView中则包含了很重要的用来显示图片的Hierarchy类,而最上层的DraweeView则包含了控制图片展示的Controller。下面将对每个view进行分析。

###1.DraweeView

DraweeView虽然是用来加载图片的,而且也是继承自ImageView,但是Facebook并不支持使用ImageView内部的一些方法。之后的Fresco方法会摒弃ImageView,改继承自View。

DraweeView初始化的时候会得到一个DraweeHolder对象,而DraweeHolder对于DraweeView便是类似于一个管家,DraweeView将内部需要的大部分事情都交给了Holder来负责管理。比如setHierarchy()和setController()方法,都是将内容交给了holder来管理。这也是一个很好的分层管理方式,值得借鉴。

在DraweeView类中,Fresco提供了PipelineDraweeController,即pipeline机制来控制整个图片的缓存下载和显示逻辑。也可以通过自定义Controller设置加载图片。

###2.GenericDraweeView

在DraweeView的子类GenericDraweeView中,作者自定义了attrs属性。意味着,使用者只要在XML文件中针对View使用相应的属性参数便可以达到设置Hierarchy的属性。这样就方便了使用者,只要在XML中就可以得到自己想要的动画以及图片展示效果。

DraweeView that creates GenericDraweeHierarchy based on XML attributes.

下面列出了GenericDraweeView其中包含了Hierarchy中可以设置的很多属性:

/* Fading animation parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeView_fadeDuration
 * Images & scale types parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeView_viewAspectRatio
 * @attr ref com.facebook.R.styleable#GenericDraweeView_placeholderImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_placeholderImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeView_retryImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_retryImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeView_failureImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_failureImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeView_progressBarImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_progressBarImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeView_progressBarAutoRotateInterval
 * @attr ref com.facebook.R.styleable#GenericDraweeView_actualImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeView_backgroundImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_overlayImage
 * @attr ref com.facebook.R.styleable#GenericDraweeView_pressedStateOverlayImage
 * Rounding parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundAsCircle
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundedCornerRadius
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundTopLeft
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundTopRight
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundBottomRight
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundBottomLeft
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundWithOverlayColor
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundingBorderWidth
 * @attr ref com.facebook.R.styleable#GenericDraweeView_roundingBorderColor
 */

GenericDraweeView中属性设置的部分和一般自定义控件类似:

TypedArray gdhAttrs = context.obtainStyledAttributes(
      attrs,
      R.styleable.GenericDraweeView);
fadeDuration = gdhAttrs.getInt(
        R.styleable.GenericDraweeView_fadeDuration,
        fadeDuration);

在完成这些设置之后,GenericDraweeView 需要一个GenericDraweeHierarchyBuilder类的对象来保存所有的属性值,而他的返回值便是一个Hierarchy。也就是说,通过Builder的build()方法,构造了一个View需要的Hierarchy,然后把XML中设置的属性都保存在Builder中等待使用。

GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
builder.setFadeDuration(fadeDuration);
...其余属性设置
setHierarchy(builder.build());

Fresco在使用DraweeView的时候虽然宽高不能设置wrap_content,但是它提供了一个可以动态设置宽高比例的方法setAspectRatio,因此它需要在GenericDraweeView的OnMeasure方法中重新设置宽高

private final AspectRatioMeasure.Spec mMeasureSpec = new AspectRatioMeasure.Spec();
    @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    mMeasureSpec.width = widthMeasureSpec;
    mMeasureSpec.height = heightMeasureSpec;
    AspectRatioMeasure.updateMeasureSpec(
        mMeasureSpec,
        mAspectRatio,
        getLayoutParams(),
        getPaddingLeft() + getPaddingRight(),
        getPaddingTop() + getPaddingBottom());
    super.onMeasure(mMeasureSpec.width, mMeasureSpec.height);
  }

AspectRatioMeasure类中的updateMeasureSpec方法,便是通过比例给View重新设置宽高。

###3.SimpleDraweeView
SimpleDraweeView类中有个静态的初始化方法initialize,这个初始化方法会在Fresco的
initialize中调用。

public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig) {
  ImagePipelineFactory.initialize(imagePipelineConfig);
  initializeDrawee(context);
}

private static void initializeDrawee(Context context) {
  sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
  SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}

其实说白了就是Fresco在初始化的时候会new一个controller(PipelineDraweeControllerBuilderSupplier类的对象),而这个controller,每个SimpleDraweeView都可以使用。SimpleDraweeView中其他的方法也都是复写的父类的方法。便不再一一叙述。