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中其他的方法也都是复写的父类的方法。便不再一一叙述。