DraweeHierachy (I)
--| SettableDraweeHierarchy (I)
------| GenericDraweeHierarchy
DraweeHierachy:
在理解获取顶层的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);
}
DraweeController
--| AbstractDraweeController
----| PipelineDraweeController
DraweeController:
AbstractDraweeController:
参照之前的分析方式,仍然采用先构造,然后具体方法的顺序
2.1 构造方法,设置了UI线程池,重试,以及手势相关的信息
public AbstractDraweeController(
DeferredReleaser deferredReleaser,
Executor uiThreadImmediateExecutor,
String id,
Object callerContext) {
mDeferredReleaser = deferredReleaser;
mUiThreadImmediateExecutor = uiThreadImmediateExecutor;
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