您的位置:首页 > 其它

Fresco之DraweeHierachy和DraweeController

2016-04-30 10:43 260 查看



4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用

DraweeHierachy (I)

--| SettableDraweeHierarchy (I)

------| GenericDraweeHierarchy

DraweeHierachy:

用于获取顶层的drawable

SettableDraweeHierachy:
图像可以被重置
图像可以设置进度
设置失败
设置重试
设置controllerOverlay

在理解获取顶层的Drawable时,需要首先理解Drawable的继承结构

先来看看DraweeHierachy的源码,发现其为接口,并且只有一个方法,就是用于获取顶层的Drawable

DraweeHierachy的源码
public interface DraweeHierarchy {

/**
* Returns the top level drawable in the corresponding hierarchy. Hierarchy should always have
* the same instance of its top level drawable.
* @return top level drawable
*/
public Drawable getTopLevelDrawable();
}


再来看看继承其的接口,SettableDraweeHierachy,如上所述

图像可以被重置
图像可以设置进度
设置失败
设置重试

设置controllerOverlay
public interface SettableDraweeHierarchy extends DraweeHierarchy {
public void reset();
public void setImage(Drawable drawable, float progress, boolean immediate);
public void setProgress(float progress, boolean immediate);
public void setFailure(Throwable throwable);
public void setRetry(Throwable throwable);
public void setControllerOverlay(Drawable drawable);
}



4.1.5.3 控制层DraweeController继承体系以及个各类的作用

DraweeController

--| AbstractDraweeController

----| PipelineDraweeController

DraweeController:

获取和设置Hieraychy
view的各种事件通知过来,controller来控制这些逻辑的操作(onAttach/onDetach/onTouchEvent/getAnimatable)

AbstractDraweeController:

最关键的功能: 实现了客户端向服务端的提交请求,即向DataSource中注册观察者,在有结果返回的时候,在主线程通知客户端更新即可,即设置Hierarychy的drawable即可

参照之前的分析方式,仍然采用先构造,然后具体方法的顺序

2.1 构造方法,设置了UI线程池,重试,以及手势相关的信息

public AbstractDraweeController(

DeferredReleaser deferredReleaser,

Executor uiThreadImmediateExecutor,

String id,

Object callerContext) {

mDeferredReleaser = deferredReleaser;

mUiThreadImmediateExecutor = uiThreadImmediateExecutor;

init(id, callerContext);

}
/**

Initializes this controller with the new id and caller context.
This allows for reusing of the existing controller instead of instantiating a new one.
This method should be called when the controller is in detached state.
@param id unique id for this controller
@param callerContext tag and context for this controller

*/

protected void initialize(String id, Object callerContext) {

init(id, callerContext);

}

private void init(String id, Object callerContext) {

mEventTracker.recordEvent(Event.ON_INIT_CONTROLLER);

// cancel deferred release

if (mDeferredReleaser != null) {

mDeferredReleaser.cancelDeferredRelease(this);

}

// reinitialize mutable state (fetch state)

mIsAttached = false;

releaseFetch();

// reinitialize optional components

if (mRetryManager != null) {

mRetryManager.init();

}

if (mGestureDetector != null) {

mGestureDetector.init();

mGestureDetector.setClickListener(this);

}

if (mControllerListener instanceof InternalForwardingListener) {

((InternalForwardingListener) mControllerListener).clearListeners();

} else {

mControllerListener = null;

}

// clear hierarchy and controller overlay

if (mSettableDraweeHierarchy != null) {

mSettableDraweeHierarchy.reset();

mSettableDraweeHierarchy.setControllerOverlay(null);

mSettableDraweeHierarchy = null;

}

mControllerOverlay = null;

// reinitialize constant state

if (FLog.isLoggable(FLog.VERBOSE)) {

FLog.v(TAG, "controller %x %s -> %s: initialize", System.identityHashCode(this), mId, id);

}

mId = id;

mCallerContext = callerContext;

}

2.2 具体方法,在这里做分析时,我们重点关注图片如何获取,因而我们关注的核心方法是onAttach(),在这里实现了图片请求的机制,以及图片获取到如何回调,如何显示到UI层的控制,在下面的程序中,看到核心的设置的方法是submitRequest()

@Override

public void onAttach() {

// 记录log

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();

}

}

此处以第一次请求为例,这样分析比较简单,查看下面的方法,在请求时,设置请求的进度为0,获取到数据源(DataSource),然后给数据源注册观察者(DataSubscriber),先查看下面的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;
//------------此处以第一次请求为例,所以wasImmediate为false
final boolean wasImmediate = mDataSource.hasResult();
//------------创建dataSubscriber的匿名内部类,交由AbstractDraweeController处理
//------------回调的结果
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();
float progress = dataSource.getProgress();
T image = dataSource.getResult();
if (image != null) {
onNewResultInternal(id, dataSource, image, progress, 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);
}
@Override
public void onProgressUpdate(DataSource<T> dataSource) {
boolean isFinished = dataSource.isFinished();
float progress = dataSource.getProgress();
onProgressUpdateInternal(id, dataSource, progress, isFinished);
}
};
//-----------给数据源注册观察者
mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
}


到了这里,一次请求已经完成了,请求的结果会在回调中执行,但是请求是如何生成的呢?我们并没有看到具体发送请求的逻辑,这个疑问我们先记录下来(暂且标记为Q1)。先来看看对于请求结果是如何处理的,以新的一次请求结果为例,onNewResultImpl()方法,而onNewResultImpl方法,以image不为空为例,最终会调用AbstractDraweeController.onNewResultInternal()方法。下面我们来看看,是如何处理这次新的请求的结果。

判断是否是想要的数据源,即查看数据信息是否是当前请求的信息,如果不是,直接释放了资源

如果是想要的数据源,创建对应的drawable,设置当前显示的drawable,释放之前缓存的drawable对象和Image对象

private void onNewResultInternal(

String id,

DataSource dataSource,

@Nullable T image,

float progress,

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;

mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);

getControllerListener().onFinalImageSet(id, getImageInfo(image), getAnimatable());

// IMPORTANT: do not execute any instance-specific code after this point

} else {

logMessageAndImage("set_intermediate_result @ onNewResult", image);

mSettableDraweeHierarchy.setImage(drawable, progress, wasImmediate);

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的操作,分析到此即可,其他的情况,我们参照这个分析的方式分析即可。下面我们来解决一下之前的Q1问题,数据源的请求是如何发送出去的,这个问题就比较复杂了,我们需要通过至少四篇的博客来分析这个请求的过程。

这里继续:http://blog.csdn.net/watertekhqx/article/details/51285727
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: