Fresco源码赏析 之 图片显示流程
Posted 楠之枫雪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fresco源码赏析 之 图片显示流程相关的知识,希望对你有一定的参考价值。
转载请注明出处:http://blog.csdn.net/u014614038/article/details/51498068
上文大概将Fresco的基本流程通了一遍,就是Frosco是如何实现了只是简单调用了setImageUrl的方法后自动将所有事情做好,这里包含很多的流程,上文大概把这些流程过了一遍,这篇文章打算将接说一下上文没有说到的一些东西,就是拿到数据后它是如何处理的,是怎么显示出来的。
上文 Fresco源码赏析 之基本流程可以看这里:
http://blog.csdn.net/u014614038/article/details/51480072根据上文的可以知道了,fresco采用的是典型的mvc模式,DraweeHierarchy 负责的是跟显示相关的,DraweeController 负责的是后台相关的,DraweeHolder主要是统筹两者的,其他还有一些事件记录等操作。我们在这里主要关心的是DraweeHierarchy 。
上文知道了一点,SimpleDraweeView它的controller是PipelineDraweeController,在它的onattach方法中会监听并获取到数据:
@Override
public void onAttach() {
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(
TAG,
"controller %x %s: onAttach: %s",
System.identityHashCode(this),
mId,
mIsRequestSubmitted ? "request already submitted" : "request needs submit");
}
mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
Preconditions.checkNotNull(mSettableDraweeHierarchy);
mDeferredReleaser.cancelDeferredRelease(this);
mIsAttached = true;
if (!mIsRequestSubmitted) {
submitRequest();//这里提交了请求
}
}
protected void submitRequest() {
mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT);
getControllerListener().onSubmit(mId, mCallerContext);
mSettableDraweeHierarchy.setProgress(0, true);
mIsRequestSubmitted = true;
mHasFetchFailed = false;
mDataSource = getDataSource();//获取数据
if (FLog.isLoggable(FLog.VERBOSE)) {
FLog.v(
TAG,
"controller %x %s: submitRequest: dataSource: %x",
System.identityHashCode(this),
mId,
System.identityHashCode(mDataSource));
}
final String id = mId;
final boolean wasImmediate = mDataSource.hasResult();
final DataSubscriber<T> dataSubscriber =
new BaseDataSubscriber<T>() {
@Override//新数据回调监听
public void onNewResultImpl(DataSource<T> dataSource) {
// isFinished must be obtained before image, otherwise we might set intermediate result
// as final image.
boolean isFinished = dataSource.isFinished();
T image = dataSource.getResult();
if (image != null) {
onNewResultInternal(id, dataSource, image, isFinished, wasImmediate);
} else if (isFinished) {
onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
}
}
@Override//失败回调监听
public void onFailureImpl(DataSource<T> dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
};
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);//传入ui线程与监听
}
mDataSource = getDataSource()是用于获取数据的,这个其实是启动后台服务进行的不是即时获取的,所以它传入了一个数据回调监听以及UI线程,当数据返回的时候这个操作要通过ui线程中执行进行相应的界面操作。
DataSource是一个接口类,很容易就找到了它 的实现的抽象类:AbstractDataSource,这个是抽象父类,不同类型的数据有不同的子类:
这个就不看了,我们看看那个mDataSource.subscribe方法:
@Override
public void subscribe(final DataSubscriber<T> dataSubscriber, final Executor executor) {
Preconditions.checkNotNull(dataSubscriber);
Preconditions.checkNotNull(executor);
boolean shouldNotify;
synchronized(this) {
if (mIsClosed) {
return;
}
if (mDataSourceStatus == DataSourceStatus.IN_PROGRESS) {
//每个Ui线程以及对应数据存起来,刷新的会遍历集合全部刷新
mSubscribers.add(Pair.create(dataSubscriber, executor));
}
shouldNotify = hasResult() || isFinished() || wasCancelled();
}
if (shouldNotify) {
//如果需要刷新就进行刷新操作
notifyDataSubscriber(dataSubscriber, executor, hasFailed(), wasCancelled());
}
}
private void notifyDataSubscriber(
final DataSubscriber<T> dataSubscriber,
final Executor executor,
final boolean isFailure,
final boolean isCancellation) {
executor.execute(//在ui线程中执行相应操作
new Runnable() {
@Override
public void run() {
if (isFailure) {//这里是相应的数据监听进行的回调
dataSubscriber.onFailure(AbstractDataSource.this);
} else if (isCancellation) {
dataSubscriber.onCancellation(AbstractDataSource.this);
} else {
dataSubscriber.onNewResult(AbstractDataSource.this);
}
}
});
}
看了没有,最终会通过ui线程进行相应数据回调,可以验证了现在是执行相应的ui操作了,我们看回去那个数据回调:
final DataSubscriber<T> dataSubscriber =
new BaseDataSubscriber<T>() {
@Override//新数据回调监听
public void onNewResultImpl(DataSource<T> dataSource) {
// isFinished must be obtained before image, otherwise we might set intermediate result
// as final image.
boolean isFinished = dataSource.isFinished();
T image = dataSource.getResult();
if (image != null) {
onNewResultInternal(id, dataSource, image, isFinished, wasImmediate);
} else if (isFinished) {
onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
}
}
@Override//失败回调监听
public void onFailureImpl(DataSource<T> dataSource) {
onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
}
};
private void onNewResultInternal(
String id,
DataSource<T> dataSource,
@Nullable T image,
boolean isFinished,
boolean wasImmediate) {
// ignore late callbacks (data source that returned the new result is not the one we expected)
if (!isExpectedDataSource(id, dataSource)) {
logMessageAndImage("ignore_old_datasource @ onNewResult", image);
releaseImage(image);
dataSource.close();
return;
}
mEventTracker.recordEvent(
isFinished ? Event.ON_DATASOURCE_RESULT : Event.ON_DATASOURCE_RESULT_INT);
// create drawable
Drawable drawable;
try {
drawable = createDrawable(image);
} catch (Exception exception) {
logMessageAndImage("drawable_failed @ onNewResult", image);
releaseImage(image);
onFailureInternal(id, dataSource, exception, isFinished);
return;
}
T previousImage = mFetchedImage;
Drawable previousDrawable = mDrawable;
mFetchedImage = image;
mDrawable = drawable;
try {
// set the new image
if (isFinished) {
logMessageAndImage("set_final_result @ onNewResult", image);
mDataSource = null;
//=======进行显示image=============
mSettableDraweeHierarchy.setImage(drawable, wasImmediate, 100);
getControllerListener().onFinalImageSet(id, getImageInfo(image), getAnimatable());
// IMPORTANT: do not execute any instance-specific code after this point
} else {
logMessageAndImage("set_intermediate_result @ onNewResult", image);
int progress = getProgress(dataSource, image);
mSettableDraweeHierarchy.setImage(drawable, wasImmediate, progress);
getControllerListener().onIntermediateImageSet(id, getImageInfo(image));
// IMPORTANT: do not execute any instance-specific code after this point
}
} finally {
if (previousDrawable != null && previousDrawable != drawable) {
releaseDrawable(previousDrawable);
}
if (previousImage != null && previousImage != image) {
logMessageAndImage("release_previous_result @ onNewResult", previousImage);
releaseImage(previousImage);
}
}
}
这里已经是在ui线程中进行操作了,包括一下事件记录,日志记录什么的,最后看到核心那句了,完成后显示图片: mSettableDraweeHierarchy.setImage(drawable, wasImmediate, 100);,所以又验证了说了那样,最终还是通过DraweeHierarchy将获取的数据后显示出来。在这里这个DraweeHierarchy是它 的子类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.
*
* <p>IMPORTANT: methods of this interface are to be used by controllers ONLY!
*
* <p>
* 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.
*
*/
好像没看懂多少,我们看看这个的实现类,发现只有一个类GenericDraweeHierarchy,那肯定是这个了,我们看看它的解析:
/**
* 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><pre name="code" class="java">
* +--o Drawable (failure image)
* 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> * 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. */
粗略来说就是它在真正的图片数据到来前会显示一些占位符图片,比如图片加载失败时显示的图片、点击重试时显示的图片、加载使的进度条等,其实它是一个有层次结构的数据体,每一个不同图片是一个层,加载中的显示的图片是一个层、失败后显示的图片是一个层、真正的数据是一个层、在不同的状态是隐藏或者显示需要的层来达到效果。它的层次结构如下那样:
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)
我觉得,真正控制的只是FadeDrawable而已,也就是说只有一个drawable而已,那些加载失败后显示的图片、重试时显示的图片等只是叠加画在上面而已。具体看看是不是这样:
先看看GenericDraweeHierarchy的成员变量,它有不同的drawable以及对应的index:
private Drawable mEmptyPlaceholderDrawable;
private final Drawable mEmptyActualImageDrawable = new ColorDrawable(Color.TRANSPARENT);
private final Drawable mEmptyControllerOverlayDrawable = new ColorDrawable(Color.TRANSPARENT);
private final Resources mResources;
private final Drawable mTopLevelDrawable;
private final FadeDrawable mFadeDrawable;
private final SettableDrawable mActualImageSettableDrawable;
private final int mPlaceholderImageIndex;
private final int mProgressBarImageIndex;
private final int mActualImageIndex;
private final int mRetryImageIndex;
private final int mFailureImageIndex;
private final int mControllerOverlayIndex;
看看那个setImage方法:
@Override
public void setImage(Drawable drawable, boolean immediate, int progress) {
drawable = maybeApplyRounding(mRoundingParams, mResources, drawable);
drawable.mutate();
mActualImageSettableDrawable.setDrawable(drawable);//这里传进去的是真正的图片数据
mFadeDrawable.beginBatchMode();
fadeOutBranches();//隐藏其他层
fadeInLayer(mActualImageIndex);//显示真正数据层
setProgress(progress);//设置进度
if (immediate) {
mFadeDrawable.finishTransitionImmediately();//刷新
}
mFadeDrawable.endBatchMode();
}
private void fadeInLayer(int index) {
if (index >= 0) {
mFadeDrawable.fadeInLayer(index);
}
}
这里我们可以确定了一点就是,图片显示的控制确实通过FadeDrawable进行控制的,我们看看这个FadeDrawable:
/**
* A drawable that fades to the specific layer.
*
* <p> Arbitrary number of layers is supported. 5 Different fade methods are supported.
* Once the transition starts we will animate layers in or out based on used fade method.
* fadeInLayer fades in specified layer to full opacity.
* fadeOutLayer fades out specified layer to zero opacity.
* fadeOutAllLayers fades out all layers to zero opacity.
* fadeToLayer fades in specified layer to full opacity, fades out all other layers to zero opacity.
* fadeUpToLayer fades in all layers up to specified layer to full opacity and
* fades out all other layers to zero opacity.
*
*/
public class FadeDrawable extends ArrayDrawable
意思就是说通过它去隐藏或者显示对应的层的,它在构造器初始化是需要传入需要的各个层:
/**
* Creates a new fade drawable.
* The first layer is displayed with full opacity whereas all other layers are invisible.
* @param layers layers to fade between
*/
public FadeDrawable(Drawable[] layers) {
super(layers);
Preconditions.checkState(layers.length >= 1, "At least one layer required!");
mLayers = layers;
mStartAlphas = new int[layers.length];
mAlphas = new int[layers.length];
mAlpha = 255;
mIsLayerOn = new boolean[layers.length];
mPreventInvalidateCount = 0;
resetInternal();
}
@Override
public void draw(Canvas canvas) {
boolean done = true;
float ratio;
switch (mTransitionState) {//这个是根据数据加载传输时的状态执行
case TRANSITION_STARTING:
// initialize start alphas and start time
System.arraycopy(mAlphas, 0, mStartAlphas, 0, mLayers.length);
mStartTimeMs = getCurrentTimeMs();
// if the duration is 0, update alphas to the target opacities immediately
ratio = (mDurationMs == 0) ? 1.0f : 0.0f;
// if all the layers have reached their target opacity, transition is done
done = updateAlphas(ratio);
mTransitionState = done ? TRANSITION_NONE : TRANSITION_RUNNING;
break;
case TRANSITION_RUNNING:
Preconditions.checkState(mDurationMs > 0);
// determine ratio based on the elapsed time
ratio = (float) (getCurrentTimeMs() - mStartTimeMs) / mDurationMs;
// if all the layers have reached their target opacity, transition is done
done = updateAlphas(ratio);
mTransitionState = done ? TRANSITION_NONE : TRANSITION_RUNNING;
break;
case TRANSITION_NONE:
// there is no transition in progress and mAlphas should be left as is.
done = true;
break;
}
for (int i = 0; i < mLayers.length; i++) {//看到核心了,实际就是把所有的层画在同一个canvas上
drawDrawableWithAlpha(canvas, mLayers[i], mAlphas[i] * mAlpha / 255);
}
if (!done) {
invalidateSelf();
}
}
看到这里忽然明白了吧,FadeDrawable是几个drawable,一切显示相关的图片会画在这个drawable上面,在不同的加载状态下显示或者隐藏相应的层就可以,而它的隐藏其实就是将透明度调到0而已,上面的初始化时有透明度的数据就是了。
现在知道为何GenericDraweeHierarchy的成员变量有不同的drawable了吧,就是不同的层的drawable还有对应的index,GenericDraweeHierarchy拿到FadeDrawable (top level drawable)以及各个层的index进行控制隐藏或者显示就可以。
GenericDraweeHierarchy(GenericDraweeHierarchyBuilder builder) {
mResources = builder.getResources();
mRoundingParams = builder.getRoundingParams();
int numLayers = 0;
// backgrounds
int numBackgrounds = (builder.getBackgrounds() != null) ? builder.getBackgrounds().size() : 0;
int backgroundsIndex = numLayers;
numLayers += numBackgrounds;//背景层
// placeholder image branch
Drawable placeholderImageBranch = builder.getPlaceholderImage();
if (placeholderImageBranch == null) {
placeholderImageBranch = getEmptyPlaceholderDrawable();
}
placeholderImageBranch = maybeApplyRounding(
mRoundingParams,
mResources,
placeholderImageBranch);
placeholderImageBranch = maybeWrapWithScaleType(
placeholderImageBranch,
builder.getPlaceholderImageScaleType());
mPlaceholderImageIndex = numLayers++;//占位符层
// actual image branch
Drawable actualImageBranch = null;
mActualImageSettableDrawable = new SettableDrawable(mEmptyActualImageDrawable);
actualImageBranch = mActualImageSettableDrawable;
actualImageBranch = maybeWrapWithScaleType(
actualImageBranch,
builder.getActualImageScaleType(),
builder.getActualImageFocusPoint());
actualImageBranch = maybeWrapWithMatrix(
actualImageBranch,
builder.getActualImageMatrix());
actualImageBranch.setColorFilter(builder.getActualImageColorFilter());
mActualImageIndex = numLayers++;//真正数据层
// progressBar image branch
Drawable progressBarImageBranch = builder.getProgressBarImage();
if (progressBarImageBranch != null) {
progressBarImageBranch = maybeWrapWithScaleType(
progressBarImageBranch,
builder.getProgressBarImageScaleType());
mProgressBarImageIndex = numLayers++;//进度条层
} else {
mProgressBarImageIndex = -1;
}
// retry image branch
Drawable retryImageBranch = builder.getRetryImage();
if (retryImageBranch != null) {
retryImageBranch = maybeWrapWithScaleType(
retryImageBranch,
builder.getRetryImageScaleType());
mRetryImageIndex = numLayers++;//重试层
} else {
mRetryImageIndex = -1;
}
// failure image branch
Drawable failureImageBranch = builder.getFailureImage();
if (failureImageBranch != null) {
failureImageBranch = maybeWrapWithScaleType(
failureImageBranch,
builder.getFailureImageScaleType());
mFailureImageIndex = numLayers++;//失败显示层
} else {
mFailureImageIndex = -1;
}
// overlays
int numOverlays = (builder.getOverlays() != null) ? builder.getOverlays().size() : 0;
int overlaysIndex = numLayers;
numLayers += numOverlays;
numLayers += (builder.getPressedStateOverlay() != null) ? 1 : 0;
// controller overlay
mControllerOverlayIndex = numLayers++;
// array of 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;
}
if (numOverlays > 0) {
int index = 0;
for (Drawable overlay : builder.getOverlays()) {
layers[overlaysIndex + index++] = overlay;
}
if (builder.getPressedStateOverlay() != null) {
layers[overlaysIndex + index++] = builder.getPressedStateOverlay();
}
}
if (mControllerOverlayIndex >= 0) {
layers[mControllerOverlayIndex] = mEmptyControllerOverlayDrawable;
}
Drawable root;
// fade drawable composed of branches
mFadeDrawable = new RootFadeDrawable(layers);
mFadeDrawable.setTransitionDuration(builder.getFadeDuration());
root = mFadeDrawable;
// rounded corners drawable (optional)
root = maybeWrapWithRoundedCorners(mRoundingParams, root);
// top-level drawable
mTopLevelDrawable = root;
mTopLevelDrawable.mutate();
resetFade();
}
现在我们看看这些层的数据是怎么传递进来的,通过代码发现这个初始化只有一个地方调用到:
public GenericDraweeHierarchy build() {
validate();
return new GenericDraweeHierarchy(this);
}
而这个会在GenericDraweeView(SimpleDraweeView的父类)初始化时执行了:
private void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
Resources resources = context.getResources();
// fading animation defaults
int fadeDuration = GenericDraweeHierarchyBuilder.DEFAULT_FADE_DURATION;
// images & scale types defaults
int placeholderId = 0;
ScalingUtils.ScaleType placeholderScaleType
= GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;
int retryImageId = 0;
ScalingUtils.ScaleType retryImageScaleType =
GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;
int failureImageId = 0;
ScalingUtils.ScaleType failureImageScaleType =
GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;
int progressBarId = 0;
ScalingUtils.ScaleType progressBarScaleType =
GenericDraweeHierarchyBuilder.DEFAULT_SCALE_TYPE;
ScalingUtils.ScaleType actualImageScaleType =
GenericDraweeHierarchyBuilder.DEFAULT_ACTUAL_IMAGE_SCALE_TYPE;
int backgroundId = 0;
int overlayId = 0;
int pressedStateOverlayId = 0;
// rounding defaults
boolean roundAsCircle = false;
int roundedCornerRadius = 0;
boolean roundTopLeft = true;
boolean roundTopRight = true;
boolean roundBottomRight = true;
boolean roundBottomLeft = true;
int roundWithOverlayColor = 0;
int roundingBorderWidth = 0;
int roundingBorderColor = 0;
int progressBarAutoRotateInterval = 0;
if (attrs != null) {
TypedArray gdhAttrs = context.obtainStyledAttributes(
attrs,
R.styleable.GenericDraweeView);
try {
// fade duration
fadeDuration = gdhAttrs.getInt(
R.styleable.GenericDraweeView_fadeDuration,
fadeDuration);
// placeholder image
placeholderId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_placeholderImage,
placeholderId);
// placeholder image scale type
placeholderScaleType = getScaleTypeFromXml(
gdhAttrs,
R.styleable.GenericDraweeView_placeholderImageScaleType,
placeholderScaleType);
// retry image
retryImageId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_retryImage,
retryImageId);
// retry image scale type
retryImageScaleType = getScaleTypeFromXml(
gdhAttrs,
R.styleable.GenericDraweeView_retryImageScaleType,
retryImageScaleType);
// failure image
failureImageId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_failureImage,
failureImageId);
// failure image scale type
failureImageScaleType = getScaleTypeFromXml(
gdhAttrs,
R.styleable.GenericDraweeView_failureImageScaleType,
failureImageScaleType);
// progress bar image
progressBarId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_progressBarImage,
progressBarId);
// progress bar image scale type
progressBarScaleType = getScaleTypeFromXml(
gdhAttrs,
R.styleable.GenericDraweeView_progressBarImageScaleType,
progressBarScaleType);
// progress bar auto rotate interval
progressBarAutoRotateInterval = gdhAttrs.getInteger(
R.styleable.GenericDraweeView_progressBarAutoRotateInterval,
0);
// actual image scale type
actualImageScaleType = getScaleTypeFromXml(
gdhAttrs,
R.styleable.GenericDraweeView_actualImageScaleType,
actualImageScaleType);
// background
backgroundId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_backgroundImage,
backgroundId);
// overlay
overlayId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_overlayImage,
overlayId);
// pressedState overlay
pressedStateOverlayId = gdhAttrs.getResourceId(
R.styleable.GenericDraweeView_pressedStateOverlayImage,
pressedStateOverlayId);
// rounding parameters
roundAsCircle = gdhAttrs.getBoolean(
R.styleable.GenericDraweeView_roundAsCircle,
roundAsCircle);
roundedCornerRadius = gdhAttrs.getDimensionPixelSize(
R.styleable.GenericDraweeView_roundedCornerRadius,
roundedCornerRadius);
roundTopLeft = gdhAttrs.getBoolean(
R.styleable.GenericDraweeView_roundTopLeft,
roundTopLeft);
roundTopRight = gdhAttrs.getBoolean(
R.styleable.GenericDraweeView_roundTopRight,
roundTopRight);
roundBottomRight = gdhAttrs.getBoolean(
R.styleable.GenericDraweeView_roundBottomRight,
roundBottomRight);
roundBottomLeft = gdhAttrs.getBoolean(
R.styleable.GenericDraweeView_roundBottomLeft,
roundBottomLeft);
roundWithOverlayColor = gdhAttrs.getColor(
R.styleable.GenericDraweeView_roundWithOverlayColor,
roundWithOverlayColor);
roundingBorderWidth = gdhAttrs.getDimensionPixelSize(
R.styleable.GenericDraweeView_roundingBorderWidth,
roundingBorderWidth);
roundingBorderColor = gdhAttrs.getColor(
R.styleable.GenericDraweeView_roundingBorderColor,
roundingBorderColor);
}
finally {
gdhAttrs.recycle();
}
}
所以就这样,会在获取xml中设置的所有资源, 转载请注明出处:http://blog.csdn.net/u014614038/article/details/51498068。
简单总结一下:
1.Fresco会的Hierarchy是有层次drawable的数据存储的地方,不同图片显示有不同的drawable,比如图片加载中显示图片、加载失败显示图片、点击重试显示图片、真正显示的图片,这些数据可以通过xml设置。
2.Fresco加载图片的不同状态会显示不同的层的drawable,其实这些层的drawable都画在一个drawable上,这个就是top level drawable,用于控制隐藏或者显示不同的层的drawable,隐藏方式只是通过设置不同drawable的透明度而已。
3.Fresco界面显示控制操作是在Hierarchy上,这个在数据回调监听时同时将操作的ui线程传递进去,所以所有的ui操作都在ui线程里面了,是安全的。
以上是关于Fresco源码赏析 之 图片显示流程的主要内容,如果未能解决你的问题,请参考以下文章