接上文《Fresco图片框架实现原理(一)》文末
private static void initializeDrawee(
Context context,
@Nullable DraweeConfig draweeConfig) {
sDraweeControllerBuilderSupplier =
new PipelineDraweeControllerBuilderSupplier(context, draweeConfig);
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier); }
在研究正真的PipelineDraweeController之前,先来看看PipelineDraweeControllerBuilder在Fresco中的构造原理和过程
从上面的函数我们一个一个往里面点
image.png
PipelineDraweeControllerBuilderSupplier是一个提供者模式,主要是为了构造PipelineDraweeControllerBuilder类
图像管道Drawee contrller builder的具体实现类
PipelineDraweeControllerBuilder.png
AbstractDraweeControllerBuilder.png
SimpleDraweeControllerBuilder接口.png
这下继承关系清除了:
继承关系图.png
SimpleDraweeControllerBuilder
/**
* Interface for simple Drawee controller builders.
*/
simple Drawee controller builders的接口
public interface SimpleDraweeControllerBuilder {
/** Sets the caller context. */
设置调用者上下文
SimpleDraweeControllerBuilder setCallerContext(Object callerContext);
/** Sets the uri. */
设置图像Uri
SimpleDraweeControllerBuilder setUri(Uri uri);
/** Sets the uri from a string. */
设置图像Uri
SimpleDraweeControllerBuilder setUri(@Nullable String uriString);
/** Sets the old controller to be reused if possible. */
如果有可能,设置旧的controller 用以重用
SimpleDraweeControllerBuilder setOldController(@Nullable DraweeController oldController);
/** Builds the specified controller. */
构建具体的DraweeController
DraweeController build();
}
AbstractDraweeControllerBuilder 源码
/**
* Base implementation for Drawee controller builders.
*/
public abstract class AbstractDraweeControllerBuilder <
BUILDER extends AbstractDraweeControllerBuilder<BUILDER, REQUEST, IMAGE, INFO>,
REQUEST,
IMAGE,
INFO>
implements SimpleDraweeControllerBuilder {
private static final ControllerListener<Object> sAutoPlayAnimationsListener =
new BaseControllerListener<Object>() {
@Override
public void onFinalImageSet(String id, @Nullable Object info, @Nullable Animatable anim) {
if (anim != null) {
anim.start();
}
}
};
private static final NullPointerException NO_REQUEST_EXCEPTION =
new NullPointerException("No image request was specified!");
// components
private final Context mContext;
private final Set<ControllerListener> mBoundControllerListeners;
// builder parameters
private @Nullable Object mCallerContext;
图片请求 ImageRequest
private @Nullable REQUEST mImageRequest;
底分辨率图片请求
private @Nullable REQUEST mLowResImageRequest;
多图片请求
private @Nullable REQUEST[] mMultiImageRequests;
private boolean mTryCacheOnlyFirst;
数据源提供者
private @Nullable Supplier<DataSource<IMAGE>> mDataSourceSupplier;
private @Nullable ControllerListener<? super INFO> mControllerListener;
private @Nullable ControllerViewportVisibilityListener mControllerViewportVisibilityListener;
是否可点击重试
private boolean mTapToRetryEnabled;
是否需要自动播放动画
private boolean mAutoPlayAnimations;
private boolean mRetainImageOnFailure;
private String mContentDescription;
// old controller to reuse
这个变量重要 重用的DraweeController ,其具体的对象,就给子类去构建
private @Nullable DraweeController mOldController;
private static final AtomicLong sIdCounter = new AtomicLong();
protected AbstractDraweeControllerBuilder(
Context context,
Set<ControllerListener> boundControllerListeners) {
mContext = context;
mBoundControllerListeners = boundControllerListeners;
init();
}
/** Initializes this builder. */
private void init() {
mCallerContext = null;
mImageRequest = null;
mLowResImageRequest = null;
mMultiImageRequests = null;
mTryCacheOnlyFirst = true;
mControllerListener = null;
mControllerViewportVisibilityListener = null;
默认false
mTapToRetryEnabled = false;
默认不自动播放
mAutoPlayAnimations = false;
mOldController = null;
mContentDescription = null;
}
....其他方法
/** Builds a regular controller. */
构建一个常规的controller
protected AbstractDraweeController buildController() {
AbstractDraweeController controller = obtainController();
controller.setRetainImageOnFailure(getRetainImageOnFailure());
controller.setContentDescription(getContentDescription());
controller.setControllerViewportVisibilityListener(getControllerViewportVisibilityListener());
maybeBuildAndSetRetryManager(controller);
maybeAttachListeners(controller);
return controller;
}
/** Concrete builder classes should override this method to return a new controller. */
这个抽象类的唯一抽象方法,又子类去实现构造具体的类
protected abstract AbstractDraweeController obtainController();
...其他方法
AbstractDraweeControllerBuilder 的作用其实就是提供DraweeControllerBuilder所需要的所有成员变量,然后具体的变量值交给子类PipelineDraweeControllerBuilder去获取实现,并设置这些成员变量
PipelineDraweeControllerBuilder源码:
/**
* Concrete implementation of ImagePipeline Drawee controller builder.
* <p/> See {@link AbstractDraweeControllerBuilder} for more details.
*/
ImagePipeline Drawee controller builder.的具体实现
public class PipelineDraweeControllerBuilder extends AbstractDraweeControllerBuilder<
PipelineDraweeControllerBuilder,
ImageRequest,
CloseableReference<CloseableImage>,
ImageInfo> {
重要的成员变量图像管道,final类型,初始化一遍不在变化,上篇文章中提到可以从ImagePipelineFactory中获取
private final ImagePipeline mImagePipeline;
重要的成员变量 PipelineDraweeControllerFactory是PipelineDraweeController工厂
private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;
@Nullable
private ImmutableList<DrawableFactory> mCustomDrawableFactories;
public PipelineDraweeControllerBuilder(
Context context,
PipelineDraweeControllerFactory pipelineDraweeControllerFactory,
ImagePipeline imagePipeline,
Set<ControllerListener> boundControllerListeners) {
super(context, boundControllerListeners);
mImagePipeline = imagePipeline;
mPipelineDraweeControllerFactory = pipelineDraweeControllerFactory;
}
@Override
public PipelineDraweeControllerBuilder setUri(@Nullable Uri uri) {
if (uri == null) {
return super.setImageRequest(null);
}
设置图片Uri的的本质是: 用此Uri构建图像请求ImageRequest,实际上Fresco加载图片,都是构造ImageRequest
ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
.setRotationOptions(RotationOptions.autoRotateAtRenderTime())
.build();
return super.setImageRequest(imageRequest);
}
@Override
public PipelineDraweeControllerBuilder setUri(@Nullable String uriString) {
if (uriString == null || uriString.isEmpty()) {
return super.setImageRequest(ImageRequest.fromUri(uriString));
}
return setUri(Uri.parse(uriString));
}
...其他方法
父级抽象类的抽象方法,重要方法 obtainController。
@Override
protected PipelineDraweeController obtainController() {
先获取之前设置的OldController
DraweeController oldController = getOldController();
PipelineDraweeController controller;
if (oldController instanceof PipelineDraweeController) {
如果oldController 是PipelineDraweeController的实例 ,就在从controller的实例上修改一些需要的值,不用再实例化一个controller
controller = (PipelineDraweeController) oldController;
controller.initialize(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
} else {
如果oldcontroller ==null 使用PipelineDraweeControllerFactory重新生成一个新的controller
controller = mPipelineDraweeControllerFactory.newController(
obtainDataSourceSupplier(),
generateUniqueControllerId(),
getCacheKey(),
getCallerContext(),
mCustomDrawableFactories);
}
return controller;
}
...其他方法
}
这个类主要是为了设置一些builder所需要的值,并且构造除乐具体的controller。PipelineDraweeController的实例
PipelineDraweeController这个类是真正的DraweeController,这个下一章在分析。
PipelineDraweeControllerFactory是PipelineDraweeController的工厂类。用于常见controller实例。
/**
* Default implementation of {@link PipelineDraweeControllerFactory}.
*/
public class PipelineDraweeControllerFactory {
private Resources mResources;
private DeferredReleaser mDeferredReleaser;
private DrawableFactory mAnimatedDrawableFactory;
private Executor mUiThreadExecutor;
private MemoryCache<CacheKey, CloseableImage> mMemoryCache;
@Nullable
private ImmutableList<DrawableFactory> mDrawableFactories;
@Nullable
private Supplier<Boolean> mDebugOverlayEnabledSupplier;
public void init(
Resources resources,
DeferredReleaser deferredReleaser,
DrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor,
MemoryCache<CacheKey, CloseableImage> memoryCache,
@Nullable ImmutableList<DrawableFactory> drawableFactories,
@Nullable Supplier<Boolean> debugOverlayEnabledSupplier) {
mResources = resources;
mDeferredReleaser = deferredReleaser;
mAnimatedDrawableFactory = animatedDrawableFactory;
mUiThreadExecutor = uiThreadExecutor;
mMemoryCache = memoryCache;
mDrawableFactories = drawableFactories;
mDebugOverlayEnabledSupplier = debugOverlayEnabledSupplier;
}
public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext) {
return newController(dataSourceSupplier, id, cacheKey, callerContext, null);
}
public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories) {
Preconditions.checkState(mResources != null, "init() not called");
// Field values passed as arguments so that any subclass of PipelineDraweeControllerFactory
// can simply override internalCreateController() and return a custom Drawee controller
PipelineDraweeController controller = internalCreateController(
mResources,
mDeferredReleaser,
mAnimatedDrawableFactory,
mUiThreadExecutor,
mMemoryCache,
mDrawableFactories,
customDrawableFactories,
dataSourceSupplier,
id,
cacheKey,
callerContext);
if (mDebugOverlayEnabledSupplier != null) {
controller.setDrawDebugOverlay(mDebugOverlayEnabledSupplier.get());
}
return controller;
}
内部创建PipelineDraweeController ,创建一个controller需要这么多参数,所以需要上面讲的重用controller的实例,只改变其中的几个成员变量值就行了。
protected PipelineDraweeController internalCreateController(
Resources resources,
DeferredReleaser deferredReleaser,
DrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor,
MemoryCache<CacheKey, CloseableImage> memoryCache,
@Nullable ImmutableList<DrawableFactory> globalDrawableFactories,
@Nullable ImmutableList<DrawableFactory> customDrawableFactories,
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
CacheKey cacheKey,
Object callerContext) {
PipelineDraweeController controller = new PipelineDraweeController(
resources,
deferredReleaser,
animatedDrawableFactory,
uiThreadExecutor,
memoryCache,
dataSourceSupplier,
id,
cacheKey,
callerContext,
globalDrawableFactories);
controller.setCustomDrawableFactories(customDrawableFactories);
return controller;
}
}