Fresco的Model层设计
上回讲到fresco的controller层,主要涉及到的是设置请求(ImageRequest)设置动画等等。下面讲述一下fresco的第三层次,Hierarchy层。
在SimpleDraweeView的最上层DraweeView中,有一个setHierarchy(),即开发者如果需要自己定义hierarchy的话,可以使用这个方法。而如果不用自定义的话。在DraweeView的子类GenericDraweeView的构造函数中便有已经设置好的hierarchy。同样的,hierarchy也需要一个builder(GenericDraweeHierarchyBuilder)才可以创建(fresco中builder模式随处可见)。是否还记得在xml中使用SimpleDraweeView时候设置的xml各种属性?这些属性在这里才真正用到。
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
// set fade duration
builder.setFadeDuration(fadeDuration);
// set images & scale types
if (placeholderId > 0) {
builder.setPlaceholderImage(resources.getDrawable(placeholderId), placeholderScaleType);
}
if (retryImageId > 0) {
builder.setRetryImage(resources.getDrawable(retryImageId), retryImageScaleType);
}
if (failureImageId > 0) {
builder.setFailureImage(resources.getDrawable(failureImageId), failureImageScaleType);
}
if (progressBarId > 0) {
Drawable progressBarDrawable = resources.getDrawable(progressBarId);
if (progressBarAutoRotateInterval > 0) {
progressBarDrawable =
new AutoRotateDrawable(progressBarDrawable, progressBarAutoRotateInterval);
}
builder.setProgressBarImage(progressBarDrawable, progressBarScaleType);
}
if (backgroundId > 0) {
builder.setBackground(resources.getDrawable(backgroundId));
}
if (overlayId > 0) {
builder.setOverlay(resources.getDrawable(overlayId));
}
if (pressedStateOverlayId > 0) {
builder.setPressedStateOverlay(getResources().getDrawable(pressedStateOverlayId));
}
builder.setActualImageScaleType(actualImageScaleType);
// set rounding parameters
if (roundAsCircle || roundedCornerRadius > 0) {
RoundingParams roundingParams = new RoundingParams();
roundingParams.setRoundAsCircle(roundAsCircle);
if (roundedCornerRadius > 0) {
roundingParams.setCornersRadii(
roundTopLeft ? roundedCornerRadius : 0,
roundTopRight ? roundedCornerRadius : 0,
roundBottomRight ? roundedCornerRadius : 0,
roundBottomLeft ? roundedCornerRadius : 0);
}
if (roundWithOverlayColor != 0) {
roundingParams.setOverlayColor(roundWithOverlayColor);
}
if (roundingBorderColor != 0 && roundingBorderWidth > 0) {
roundingParams.setBorder(roundingBorderColor, roundingBorderWidth);
}
builder.setRoundingParams(roundingParams);
}
setHierarchy(builder.build());
通过GenericDraweeHierarchyBuilder设置好属性之后,调用build()方法便会生成一个GenericDraweeHierarchy,那么他的图片是从哪里来的呢,GenericDraweeHierarchy实现了一个接口SettableDraweeHierarchy,这个接口中定义了图片加载过程中包括成功,失败,错误时候的情况。我们看一下成功之后的回调接口:
@Override
public void setImage(Drawable drawable, float progress, boolean immediate) {
drawable = maybeApplyRoundingBitmapOnly(mRoundingParams, mResources, drawable);
drawable.mutate();
mActualImageSettableDrawable.setDrawable(drawable);
mFadeDrawable.beginBatchMode();
fadeOutBranches();
fadeInLayer(mActualImageIndex);
setProgress(progress);
if (immediate) {
mFadeDrawable.finishTransitionImmediately();
}
mFadeDrawable.endBatchMode();
}
上一段代码中就将得到的图片fadeInLayer,而其他站位图则都进行了fadeOut,所以此时getTopDrawable时,便是获取到的最新的图片。那么又是什么时候去获取的图片呢。这时候需要回去看一下在AbstractDraweeController(用来控制图片显示的)中的Hierarchy便是直接使用的SettableDraweeHierarchy,也就是说,Controller中已经持有了SettableDraweeHierarchy的一个实例。
@Override
public @Nullable
DraweeHierarchy getHierarchy() {
return mSettableDraweeHierarchy;
}
之后的就是上一篇文章中提到的,在AbstractDraweeController中如果发请求的话,会调用到submitRequest()方法,在此方法中会开线程去下载图片,如果图片下载成功回调至onNewResultImpl()方法中,紧接着又会执行到onNewResultInternal()方法中,这个方法中就会有这样一句:
mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);
此时之前的SimpleDraweeView中的Hierarvhy便有了真正的图片,而之前在显示的时候都是占位图,此时再获取的时候就会发现,topDrawable便开始有了真正的图片可以显示。这样整个图片从请求到请求完成,到如何显示的流程便分析完成了。