Fresco解析
来源:互联网 发布:vb cmd命令 进入某目录 编辑:程序博客网 时间:2024/06/05 19:01
Fresco解析
1.Fresco初始化
1.Fresco调用时必须先调用Fresco.initialize(Context)
(ImagePipelineFactory.java)
private static PipelineDraweeControllerBuilderSupplier sDraweeControllerBuilderSupplier;/** Initializes Fresco with the default config. */public static void initialize(Context context) { ImagePipelineFactory.initialize(context); initializeDrawee(context);}private static void initializeDrawee(Context context) { sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context); SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);}
initilize方法做了两件事 :
1. 使用ImagePipelineConfig创建ImagePipelineFactory, factory可以使用config创建出ImagePipeline.
ImagePipline是什么?官方文档是这么说的:
Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要做的每个事情。
大致流程如下:
- 检查内存缓存,如有,返回
- 后台线程开始后续工作
- 检查是否在未解码内存缓存中。如有,解码,变换,返回,然后缓存到内存缓存中。
- 检查是否在文件缓存中,如果有,变换,返回。缓存到未解码缓存和内存缓存中。
- 从网络或者本地加载。加载完成后,解码,变换,返回。存到各个缓存中。
既然本身就是一个图片加载组件,那么一图胜千言。
上图中,disk cache实际包含了未解码的内存缓存在内,统一在一起只是为了逻辑稍微清楚一些。关于缓存,更多细节可以参考这里。
Image pipeline 可以从本地文件加载文件,也可以从网络。支持PNG,GIF,WebP, JPEG。
- 把
sDraweeControllerBuilderSupplier
传给SimpleDraweeView,SimpleDraweeView 使用setImageURI加载图片时,前者会生成DraweeController实现具体的加载流程。
1.ImagePipelineFactory.initialize(context)
先看一下ImagePipelineFactory的initialize方法:(ImagePipelineFactory.java)
private static ImagePipelineFactory sInstance = null;private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;/** Gets the instance of {@link ImagePipelineFactory}. */public static ImagePipelineFactory getInstance() { return Preconditions.checkNotNull(sInstance, "ImagePipelineFactory was not initialized!");}/** Initializes {@link ImagePipelineFactory} with default config. */public static void initialize(Context context) { initialize(ImagePipelineConfig.newBuilder(context).build());}/** Initializes {@link ImagePipelineFactory} with the specified config. */public static void initialize(ImagePipelineConfig imagePipelineConfig) { sInstance = new ImagePipelineFactory(imagePipelineConfig);}
ImagePipelineConfig使用的Builder模式,AlertDialog使用的也是类似的模式 (ImagePipelineConfig.java)
/** * Master configuration class for the image pipeline library. * * To use: * <code> * ImagePipelineConfig config = ImagePipelineConfig.newBuilder() * .setXXX(xxx) * .setYYY(yyy) * .build(); * ImagePipelineFactory factory = new ImagePipelineFactory(config); * ImagePipeline pipeline = factory.getImagePipeline(); * </code> * * <p>This should only be done once per process. */public class ImagePipelineConfig {// There are a lot of parameters in this class. Please follow strict alphabetical order.@Nullable private final AnimatedImageFactory mAnimatedImageFactory;private final Bitmap.Config mBitmapConfig;private final Supplier<MemoryCacheParams> mBitmapMemoryCacheParamsSupplier;。。。。。。private ImagePipelineConfig(Builder builder) { mAnimatedImageFactory = builder.mAnimatedImageFactory; mBitmapMemoryCacheParamsSupplier = builder.mBitmapMemoryCacheParamsSupplier == null ? new DefaultBitmapMemoryCacheParamsSupplier( (ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) : builder.mBitmapMemoryCacheParamsSupplier; mBitmapConfig = builder.mBitmapConfig == null ? Bitmap.Config.ARGB_8888 : builder.mBitmapConfig;。。。。。。}//调用的唯一入口(Builder的构造方法是private的)public static Builder newBuilder(Context context) { return new Builder(context);}public static class Builder { private AnimatedImageFactory mAnimatedImageFactory; private Bitmap.Config mBitmapConfig; private Supplier<MemoryCacheParams> mBitmapMemoryCacheParamsSupplier; 。。。 。。。private Builder(Context context) { // Doesn't use a setter as always required. mContext = Preconditions.checkNotNull(context);}public Builder setAnimatedImageFactory(AnimatedImageFactory animatedImageFactory) { mAnimatedImageFactory = animatedImageFactory; return this;}public Builder setBitmapsConfig(Bitmap.Config config) { mBitmapConfig = config; return this;}//生成ImagePipelineConfigpublic ImagePipelineConfig build() { return new ImagePipelineConfig(this);}}}
ImagePipelineFactory用于创建ImagePipeline,文档里强烈推荐把ImagePipelineFactory和ImagePipeline都作为单例实现:(ImagePipelineFactory.java)
/*** Factory class for the image pipeline.** <p>This class constructs the pipeline and its dependencies from other libraries.** <p>As the pipeline object can be quite expensive to create, it is strongly* recommended that applications create just one instance of this class* and of the pipeline.*/@NotThreadSafepublic class ImagePipelineFactory { private static ImagePipelineFactory sInstance = null; /** Gets the instance of {@link ImagePipelineFactory}. */ public static ImagePipelineFactory getInstance() { return Preconditions.checkNotNull(sInstance, "ImagePipelineFactory was not initialized!"); } 。。。。public ImagePipeline getImagePipeline() { if (mImagePipeline == null) { mImagePipeline = new ImagePipeline( getProducerSequenceFactory(), mConfig.getRequestListeners(), mConfig.getIsPrefetchEnabledSupplier(), getBitmapMemoryCache(), getEncodedMemoryCache(), getMainBufferedDiskCache(), getSmallImageBufferedDiskCache(), mConfig.getCacheKeyFactory(), mThreadHandoffProducerQueue); } return mImagePipeline;}
2.initializeDrawee(context)
再看一下initialize的第二步 initializeDrawee(context)
;
Fresco的initializeDrawee(context)
方法: (Fresco.java)
private static PipelineDraweeControllerBuilderSupplier sDraweeControllerBuilderSupplier;private static void initializeDrawee(Context context) { sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context); SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);}
PipelineDraweeControllerBuilderSupplier也是作为一个单例存在。
1.PipelineDraweeControllerBuilderSupplier 构造方法
public class PipelineDraweeControllerBuilderSupplier implements Supplier<PipelineDraweeControllerBuilder>{public PipelineDraweeControllerBuilderSupplier(Context context) { this(context, ImagePipelineFactory.getInstance());}。。。}
PipelineDraweeControllerBuilderSupplier 实现了Supplier接口,Supplier引用于Google Guava项目(https://github.com/google/guava)
/** * A class that can supply objects of a single type. Semantically, this could * be a factory, generator, builder, closure, or something else entirely. No * guarantees are implied by this interface. * * @author Harry Heymann * @since 2.0 (imported from Google Collections Library) */public interface Supplier<T> { /** * Retrieves an instance of the appropriate type. The returned object may or * may not be a new instance, depending on the implementation. * * @return an instance of the appropriate type */ T get();}
PipelineDraweeControllerBuilderSupplier 的构造方法如下:(PipelineDraweeControllerBuilderSupplier.java)
private final Context mContext;private final ImagePipeline mImagePipeline;private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;private final Set<ControllerListener> mBoundControllerListeners;public PipelineDraweeControllerBuilderSupplier(Context context) { this(context, ImagePipelineFactory.getInstance());}public PipelineDraweeControllerBuilderSupplier( Context context, ImagePipelineFactory imagePipelineFactory) { this(context, imagePipelineFactory, null);}public PipelineDraweeControllerBuilderSupplier( Context context, ImagePipelineFactory imagePipelineFactory, Set<ControllerListener> boundControllerListeners) { mContext = context; mImagePipeline = imagePipelineFactory.getImagePipeline(); mPipelineDraweeControllerFactory = new PipelineDraweeControllerFactory( context.getResources(), DeferredReleaser.getInstance(), imagePipelineFactory.getAnimatedDrawableFactory(), UiThreadImmediateExecutorService.getInstance()); mBoundControllerListeners = boundControllerListeners;}
这里也通过ImagePipelineFactory.getImagePipeline创建了ImagePipeline,
PipelineDraweeControllerFactory是一个工厂类,用于创建PipelineDraweeController,DraweeController用于处理图片加载的逻辑,后面再说。
2.SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier)
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier) (SimpleDraweeView.java)
/*** This view takes a uri as input and internally builds and sets a controller.** <p>This class must be statically initialized in order to be used. If you are using the Fresco* image pipeline, use {@link com.facebook.drawee.backends.pipeline.Fresco#initialize} to do this.*/public class SimpleDraweeView extends GenericDraweeView { private static Supplier<? extends SimpleDraweeControllerBuilder> sDraweeControllerBuilderSupplier; /** Initializes {@link SimpleDraweeView} with supplier of Drawee controller builders. */ public static void initialize( Supplier<? extends SimpleDraweeControllerBuilder> draweeControllerBuilderSupplier) { sDraweeControllerBuilderSupplier = draweeControllerBuilderSupplier; } /** Shuts {@link SimpleDraweeView} down. */ public static void shutDown() { sDraweeControllerBuilderSupplier = null; } private SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder; public SimpleDraweeView(Context context, GenericDraweeHierarchy hierarchy) { super(context, hierarchy); init(); } public SimpleDraweeView(Context context) { super(context); init(); } public SimpleDraweeView(Context context, AttributeSet attrs) { super(context, attrs); init(); } ….. private void init() { if (isInEditMode()) { return; } Preconditions.checkNotNull( sDraweeControllerBuilderSupplier, "SimpleDraweeView was not initialized!"); mSimpleDraweeControllerBuilder = sDraweeControllerBuilderSupplier.get(); } protected SimpleDraweeControllerBuilder getControllerBuilder() { return mSimpleDraweeControllerBuilder; } /** * Displays an image given by the uri. * * @param uri uri of the image * @undeprecate */ @Override public void setImageURI(Uri uri) { setImageURI(uri, null); } /** * Displays an image given by the uri. * * @param uri uri of the image * @param callerContext caller context */ public void setImageURI(Uri uri, @Nullable Object callerContext) { DraweeController controller = mSimpleDraweeControllerBuilder .setCallerContext(callerContext) .setUri(uri) .setOldController(getController()) .build(); setController(controller); }}
SimpleDraweeView在init()方法中调用sDraweeControllerBuilderSupplier.get(),把结果赋给了成员变量mSimpleDraweeControllerBuilder,
来看一下它的get()方法:(PipelineDraweeControllerBuilder.java)
@Overridepublic PipelineDraweeControllerBuilder get() { return new PipelineDraweeControllerBuilder( mContext, mPipelineDraweeControllerFactory, mImagePipeline, mBoundControllerListeners);}
创建出PipelineDraweeControllerBuilder,主要需要PipelineDraweeControllerFactory和ImagePipeline参数。
这里的mSimpleDraweeControllerBuilder的类型其实就是PipelineDraweeControllerBuilder
首先看一下PipelineDraweeControllerBuilder的继承关系:
SimpleDraweeControllerBuilder是最上层的接口,暴露了最基本的5个方法,设置context,设置uri,复用controller,生成controller.
AbstractDraweeControllerBuilder是基本实现
2.setImageUri
setImageURI是Fresco加载图片的唯一方法 (SimpleDraweeView.java)
/** * Displays an image given by the uri. * * @param uri uri of the image * @param callerContext caller context */ public void setImageURI(Uri uri, @Nullable Object callerContext) { DraweeController controller = mSimpleDraweeControllerBuilder .setCallerContext(callerContext) .setUri(uri) .setOldController(getController()) .build(); setController(controller); }
mSimpleDraweeControllerBuilder从之前的代码中可以看出,它的类型是PipelineDraweeControllerBuilder。
1.mSimpleDraweeControllerBuilder.build()
首先是build()方法,具体调用在父类AbstractDraweeControllerBuilder中:(AbstractDraweeControllerBuilder.java)
/** Builds the specified controller. */@Overridepublic AbstractDraweeController build() { validate(); // if only a low-res request is specified, treat it as a final request. if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) { mImageRequest = mLowResImageRequest; mLowResImageRequest = null; } return buildController();}/** Builds a regular controller. */protected AbstractDraweeController buildController() { AbstractDraweeController controller = obtainController(); controller.setRetainImageOnFailure(getRetainImageOnFailure()); //失败时是否显示上一次加载的图片。默认为false maybeBuildAndSetRetryManager(controller); //是否增加点击重试 TODO maybeAttachListeners(controller); return controller;}/** Concrete builder classes should override this method to return a new controller. */protected abstract AbstractDraweeController obtainController(); //具体的子类实现
build方法会对成员变量进行赋值,然后调用buildController()
buildController调用obtainController(),然后增加失败时是否显示上一张图片和点击重试加载的逻辑,最后返回controller
obtainController是abstract的,具体实现在子类PipelineDraweeControllerBuilder中,
看一下PipelineDraweeControllerBuilder的具体实现:(PipelineDraweeControllerBuilder.java)
private final ImagePipeline mImagePipeline;private final PipelineDraweeControllerFactory mPipelineDraweeControllerFactory;public PipelineDraweeControllerBuilder( Context context, PipelineDraweeControllerFactory pipelineDraweeControllerFactory, ImagePipeline imagePipeline, Set<ControllerListener> boundControllerListeners) { super(context, boundControllerListeners); mImagePipeline = imagePipeline; mPipelineDraweeControllerFactory = pipelineDraweeControllerFactory;}@Overrideprotected PipelineDraweeController obtainController() { DraweeController oldController = getOldController(); PipelineDraweeController controller; if (oldController instanceof PipelineDraweeController) { //复用old controller controller = (PipelineDraweeController) oldController; controller.initialize( obtainDataSourceSupplier(), generateUniqueControllerId(), getCallerContext()); } else { //new controller controller = mPipelineDraweeControllerFactory.newController( obtainDataSourceSupplier(), generateUniqueControllerId(), getCallerContext()); } return controller;}
注意这里的代码27行,obtainDataSourceSupplier()
,这个方法创建了DataSource,后边再说。
先讲一下PipelineDraweeControllerBuilder的初始化过程:
Fresco.initialize(context)
—>Fresco.initializeDrawee(context)
—>new PipelineDraweeControllerBuilderSupplier(),构造函数中同时new了PipelineDraweeControllerFactory,该工厂类用于new PipelineDraweeController (PipelineDraweeControllerFactory.java)
public PipelineDraweeController newController( Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier, String id, Object callerContext) { return new PipelineDraweeController( mResources, mDeferredReleaser, mAnimatedDrawableFactory, mUiThreadExecutor, dataSourceSupplier, id, callerContext);}
—>SimpleDraweeView.initialize(supplier),把supplier赋值给SimpleDraweeView
—>SimpleDraweeView.init(),调用supplier的get()方法生成了成员变量SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder
2.setController
首先看一下DraweeView,DraweeHolder,DraweeController,DraweeHierarchy的关系:
三者的关系如下图所示,DraweeView 会通过DraweeHolder把获得的 Event 转发给 Controller,然后 Controller 根据 Event 来决定是否需要显示和隐藏 图像(包括动画),而这些图像都存储在 Hierarchy 中,最后 DraweeView 绘制时直接通过 getTopLevelDrawable 就可以获取需要显示的图像。
DraweeView的setController调用的是父类的方法:(DraweeView.java)
/*** View that displays a {@link DraweeHierarchy}.** <p> Hierarchy should be set prior to using this view. See {@code setHierarchy}. Because creating* a hierarchy is an expensive operation, it is recommended this be done once per view, typically* near creation time.** <p> In order to display an image, controller has to be set. See {@code setController}.* <p> Although ImageView is subclassed instead of subclassing View directly, this class does not* support ImageView's setImageXxx, setScaleType and similar methods. Extending ImageView is a short* term solution in order to inherit some of its implementation (padding calculations, etc.).* This class is likely to be converted to extend View directly in the future, so avoid using* ImageView's methods and properties (T5856175).*/public class DraweeView<DH extends DraweeHierarchy> extends ImageView { private DraweeHolder<DH> mDraweeHolder; 。。。/** Sets the controller. */public void setController(@Nullable DraweeController draweeController) { mDraweeHolder.setController(draweeController); super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());}}
DraweeView中有成员变量mDraweeHolder,setController最终调用的mDraweeHolder的同名方法,另外会通过mDraweeHolder.getTopLevelDrawable()更新现在要显示的图片。
看一下DraweeHolder的setController方法:(DraweeHolder.java)
/*** Sets a new controller.*/public void setController(@Nullable DraweeController draweeController) { boolean wasAttached = mIsControllerAttached; if (wasAttached) { detachController(); } // Clear the old controller if (mController != null) { mEventTracker.recordEvent(Event.ON_CLEAR_OLD_CONTROLLER); mController.setHierarchy(null); } mController = draweeController; if (mController != null) { mEventTracker.recordEvent(Event.ON_SET_CONTROLLER); **mController.setHierarchy(mHierarchy); } else { mEventTracker.recordEvent(Event.ON_CLEAR_CONTROLLER); } if (wasAttached) { attachController(); }}
看一下attachController()方法:(DraweeHolder.java)
private void attachController() { if (mIsControllerAttached) { return; } mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER); mIsControllerAttached = true; if (mController != null && mController.getHierarchy() != null) { mController.onAttach(); }}
调用了DraweeController的onAttach方法,具体实现在DraweeController的子类AbstractDraweeController中:(AbstractDraweeController.java)
@Overridepublic void onAttach() { ... mDeferredReleaser.cancelDeferredRelease(this); mIsAttached = true; if (!mIsRequestSubmitted) { submitRequest(); }}
1.AbstractDraweeController的submitRequest()
看一下AbstractDraweeController的submitRequest()方法:(AbstractDraweeController.java)
protected void submitRequest() { final T closeableImage = getCachedImage(); if (closeableImage != null) { mDataSource = null; mIsRequestSubmitted = true; mHasFetchFailed = false; mEventTracker.recordEvent(Event.ON_SUBMIT_CACHE_HIT); getControllerListener().onSubmit(mId, mCallerContext); onNewResultInternal(mId, mDataSource, closeableImage, 1.0f, true, true); return; } 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(); 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);}
17行getDataSource()
给mDataSource变量赋值
28-53行,创建了观察者DataSubscriber
54行,执行订阅操作
2.DataSource 及DataSubscriber介绍
/** * An alternative to Java Futures for the image pipeline. * * <p>Unlike Futures, DataSource can issue a series of results, rather than just one. A prime * example is decoding progressive images, which have a series of intermediate results before the * final one. * * <p>DataSources MUST be closed (close() is called on the DataSource) else resources may leak. * *@param <T> the type of the result */public interface DataSource<T> { /** * @return true if the data source is closed, false otherwise */ boolean isClosed(); /** * The most recent result of the asynchronous computation. * * <p>The caller gains ownership of the object and is responsible for releasing it. * Note that subsequent calls to getResult might give different results. Later results should be * considered to be of higher quality. * * <p>This method will return null in the following cases: * <ul> * <li>when the DataSource does not have a result ({@code hasResult} returns false). * <li>when the last result produced was null. * </ul> * @return current best result */ @Nullable T getResult(); /** * @return true if any result (possibly of lower quality) is available right now, false otherwise */ boolean hasResult(); /** * @return true if request is finished, false otherwise */ boolean isFinished(); /** * @return true if request finished due to error */ boolean hasFailed(); /** * @return failure cause if the source has failed, else null */ @Nullable Throwable getFailureCause(); /** * @return progress in range [0, 1] */ float getProgress(); /** * Cancels the ongoing request and releases all associated resources. * * <p>Subsequent calls to {@link #getResult} will return null. * @return true if the data source is closed for the first time */ boolean close(); /** * Subscribe for notifications whenever the state of the DataSource changes. * * <p>All changes will be observed on the provided executor. * @param dataSubscriber * @param executor */ void subscribe(DataSubscriber<T> dataSubscriber, Executor executor);}
下边看看DataSubscriber:
/** * Subscribes to DataSource<T>. * @param <T> */public interface DataSubscriber<T> { /** * Called whenever a new value is ready to be retrieved from the DataSource. * * <p>To retrieve the new value, call {@code dataSource.getResult()}. * * <p>To determine if the new value is the last, use {@code dataSource.isFinished()}. * * @param dataSource */ void onNewResult(DataSource<T> dataSource); /** * Called whenever an error occurs inside of the pipeline. * * <p>No further results will be produced after this method is called. * * <p>The throwable resulting from the failure can be obtained using * {@code dataSource.getFailureCause}. * * @param dataSource */ void onFailure(DataSource<T> dataSource); /** * Called whenever the request is cancelled (a request being cancelled means that is was closed * before it finished). * * <p>No further results will be produced after this method is called. * * @param dataSource */ void onCancellation(DataSource<T> dataSource); /** * Called when the progress updates. * * @param dataSource */ void onProgressUpdate(DataSource<T> dataSource);}
DataSubscriber有1个base实现,BaseDataSubscriber:
/** * Base implementation of {@link DataSubscriber} that ensures that the data source is closed when * the subscriber has finished with it. * <p> * Sample usage: * <pre> * <code> * dataSource.subscribe( * new BaseDataSubscriber() { * {@literal @}Override * public void onNewResultImpl(DataSource dataSource) { * // Store image ref to be released later. * mCloseableImageRef = dataSource.getResult(); * // Use the image. * updateImage(mCloseableImageRef); * // No need to do any cleanup of the data source. * } * * {@literal @}Override * public void onFailureImpl(DataSource dataSource) { * // No cleanup of the data source required here. * } * }); * </code> * </pre> */public abstract class BaseDataSubscriber<T> implements DataSubscriber<T> { @Override public void onNewResult(DataSource<T> dataSource) { // isFinished() should be checked before calling onNewResultImpl(), otherwise // there would be a race condition: the final data source result might be ready before // we call isFinished() here, which would lead to the loss of the final result // (because of an early dataSource.close() call). final boolean shouldClose = dataSource.isFinished(); try { onNewResultImpl(dataSource); } finally { if (shouldClose) { dataSource.close(); } } } @Override public void onFailure(DataSource<T> dataSource) { try { onFailureImpl(dataSource); } finally { dataSource.close(); } } @Override public void onCancellation(DataSource<T> dataSource) { } @Override public void onProgressUpdate(DataSource<T> dataSource) { } protected abstract void onNewResultImpl(DataSource<T> dataSource); protected abstract void onFailureImpl(DataSource<T> dataSource);}
DataSource 是一个 interface, 功能与JDK中的Future类似,但是相比于Future,它的先进之处则在于 不仅仅只生产一个单一的结果,而是能够提供系列结果。
Unlike Futures, DataSource can issue a series of results, rather than just one.
最典型的用途就是渐进式加载图片时可以提供加载中的中间数据。
DataSubscriber 和 DataSource 构成了一个观察者模式。
Datasource 提供了注册方法。
void subscribe(DataSubscriber dataSubscriber, Executor executor);
通过 subscribe 方法我们可以把 DataSubscriber 注册成为 DataSource 的观察者,然后当 DataSource 的数据发生变化时,在 Executor 中通知所有的观察者 - DataSubscriber。
DataSubscriber 会响应数据的四种变化。
- onNewResult
- onFailure
- onCancellation
- onProgressUpdate
使用Executor来通知观察者是比较高明的,这样做可以让回调方法的执行线程交由 DataSubscriber 来处理,增加了灵活性。
AbstractDataSource是DataSource的抽象实现,它管理了事件的各种状态,并且当状态变化时,会发送通知。
官方也建议其他的DataSource都继承AbstractDataSource
/** * An abstract implementation of {@link DataSource} interface. * * <p> It is highly recommended that other data sources extend this class as it takes care of the * state, as well as of notifying listeners when the state changes. * * <p> Subclasses should override {@link #closeResult(T result)} if results need clean up * * @param <T> */public abstract class AbstractDataSource<T> implements DataSource<T> { /** * Describes state of data source */ private enum DataSourceStatus { // data source has not finished yet IN_PROGRESS, // data source has finished with success SUCCESS, // data source has finished with failure FAILURE, }
看一下subscribe方法的具体实现:(AbstractDataSource.java)
@Overridepublic 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) { 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( new Runnable() { @Override public void run() { if (isFailure) { dataSubscriber.onFailure(AbstractDataSource.this); } else if (isCancellation) { dataSubscriber.onCancellation(AbstractDataSource.this); } else { dataSubscriber.onNewResult(AbstractDataSource.this); } } });}
notifyDataSubscriber
方法中使用了executor,该参数中由subscribe方法传入,提高了通知方法的灵活性。
现在返回到AbstractDraweeController的submitRequest()方法:
17行getDataSource()给mDataSource变量赋值
28-53行,创建了观察者DataSubscriber
54行,执行订阅操作
getDataSource在AbstractDraweeController中是abstract的,具体实现在子类PipelineDraweeController中:(PipelineDraweeController.java)
private Supplier<DataSource<CloseableReference<CloseableImage>>> mDataSourceSupplier;public PipelineDraweeController( Resources resources, DeferredReleaser deferredReleaser, AnimatedDrawableFactory animatedDrawableFactory, Executor uiThreadExecutor, MemoryCache<CacheKey, CloseableImage> memoryCache, Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier, String id, CacheKey cacheKey, Object callerContext) { super(deferredReleaser, uiThreadExecutor, id, callerContext); mResources = resources; mAnimatedDrawableFactory = animatedDrawableFactory; mMemoryCache = memoryCache; mCacheKey = cacheKey; init(dataSourceSupplier);}/*** Initializes this controller with the new data source supplier, 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 dataSourceSupplier data source supplier* @param id unique id for this controller* @param callerContext tag and context for this controller*/public void initialize( Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier, String id, CacheKey cacheKey, Object callerContext) { //该方法是复用old controller时调用的 super.initialize(id, callerContext); init(dataSourceSupplier); mCacheKey = cacheKey;}private void init(Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier) { mDataSourceSupplier = dataSourceSupplier;}@Overrideprotected DataSource<CloseableReference<CloseableImage>> getDataSource() { if (FLog.isLoggable(FLog.VERBOSE)) { FLog.v(TAG, "controller %x: getDataSource", System.identityHashCode(this)); } return mDataSourceSupplier.get();}
可以看出DataSourceSupplier的赋值是在初始化PipelineDraweeController时调用的,
PipelineDraweeController 初始化是什么时候呢?
回到SimpleDraweeView的setImageUri方法:
public void setImageURI(Uri uri, @Nullable Object callerContext) { DraweeController controller = mSimpleDraweeControllerBuilder .setCallerContext(callerContext) .setUri(uri) .setOldController(getController()) .build(); setController(controller); }
这里创建了DraweeController,具体实现在PipelineDraweeControllerBuilder.java中
@Overrideprotected PipelineDraweeController obtainController() { DraweeController oldController = getOldController(); PipelineDraweeController controller; if (oldController instanceof PipelineDraweeController) { //复用old controller controller = (PipelineDraweeController) oldController; controller.initialize( obtainDataSourceSupplier(), generateUniqueControllerId(), getCallerContext()); } else { //new controller controller = mPipelineDraweeControllerFactory.newController( obtainDataSourceSupplier(), generateUniqueControllerId(), getCallerContext()); } return controller;}
上边提到过obtainDataSourceSupplier()
方法,这个方法创建出了真正的DataSourceSupplier,具体实现在父类中:(AbstractDraweeControllerBuilder.java)
/** Gets the top-level data source supplier to be used by a controller. */protected Supplier<DataSource<IMAGE>> obtainDataSourceSupplier() { if (mDataSourceSupplier != null) { return mDataSourceSupplier; } Supplier<DataSource<IMAGE>> supplier = null; // final image supplier; if (mImageRequest != null) { supplier = getDataSourceSupplierForRequest(mImageRequest); } else if (mMultiImageRequests != null) { //多个图片地址 supplier = getFirstAvailableDataSourceSupplier(mMultiImageRequests, mTryCacheOnlyFirst); } // increasing-quality supplier; highest-quality supplier goes first if (supplier != null && mLowResImageRequest != null) { //不同分辨率 List<Supplier<DataSource<IMAGE>>> suppliers = new ArrayList<>(2); suppliers.add(supplier); suppliers.add(getDataSourceSupplierForRequest(mLowResImageRequest)); supplier = IncreasingQualityDataSourceSupplier.create(suppliers); } // no image requests; use null data source supplier if (supplier == null) { supplier = DataSources.getFailedDataSourceSupplier(NO_REQUEST_EXCEPTION); } return supplier;}。。。/** Creates a data source supplier for the given image request. */protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest(REQUEST imageRequest) { return getDataSourceSupplierForRequest(imageRequest, /* bitmapCacheOnly */ false);}/** Creates a data source supplier for the given image request. */protected Supplier<DataSource<IMAGE>> getDataSourceSupplierForRequest( final REQUEST imageRequest, final boolean bitmapCacheOnly) { final Object callerContext = getCallerContext(); return new Supplier<DataSource<IMAGE>>() { @Override public DataSource<IMAGE> get() { return getDataSourceForRequest(imageRequest, callerContext, bitmapCacheOnly); } @Override public String toString() { return Objects.toStringHelper(this) .add("request", imageRequest.toString()) .toString(); } };}。。。/*** Concrete builder classes should override this method to return a data source for the request.** <p/>IMPORTANT: Do NOT ever call this method directly. This method is only to be called from* a supplier created in {#code getDataSourceSupplierForRequest(REQUEST, boolean)}.** <p/>IMPORTANT: Make sure that you do NOT use any non-final field from this method, as the field* may change if the instance of this builder gets reused. If any such field is required, override* {#code getDataSourceSupplierForRequest(REQUEST, boolean)}, and store the field in a final* variable (same as it is done for callerContext).*/protected abstract DataSource<IMAGE> getDataSourceForRequest( final REQUEST imageRequest, final Object callerContext, final boolean bitmapCacheOnly);
- 首先是11-13行,单个url地址的话肯定调用的是
getDataSourceSupplierForRequest()
, - 然后是34-36行,调用了它的重载方法
3.下边的39-54行,new出一个Supplier,并暴露出抽象方法getDataSourceForRequest
,需要子类实现
具体实现在子类中:(PipelineDraweeControllerBuilder.java)
@Overrideprotected DataSource<CloseableReference<CloseableImage>> getDataSourceForRequest( ImageRequest imageRequest, Object callerContext, boolean bitmapCacheOnly) { if (bitmapCacheOnly) { return mImagePipeline.fetchImageFromBitmapCache(imageRequest, callerContext); } else { return mImagePipeline.fetchDecodedImage(imageRequest, callerContext); }}
fetchImageFromBitmapCache
是从缓存中获取中,暂时不看,我们需要研究的fetchDecodedImage
,从网络获取。
3.ImagePipeline fetchDecodedImage
/*** Submits a request for execution and returns a DataSource representing the pending decoded* image(s).* <p>The returned DataSource must be closed once the client has finished with it.* @param imageRequest the request to submit* @return a DataSource representing the pending decoded image(s)*/public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage( ImageRequest imageRequest, Object callerContext) { try { Producer<CloseableReference<CloseableImage>> producerSequence = mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest); return submitFetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, callerContext); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); }}
这里有两个关键步骤
1. mProducerSequenceFactory.getDecodedImageProducerSequence
2. submitFetchRequest
1.Producer和Consumer
/*** Building block for image processing in the image pipeline.** <p> Execution of image request consists of multiple different tasks such as network fetch,* disk caching, memory caching, decoding, applying transformations etc. Producer<T> represents* single task whose result is an instance of T. Breaking entire request into sequence of* Producers allows us to construct different requests while reusing the same blocks.** <p> Producer supports multiple values and streaming.** @param <T>*/public interface Producer<T> { /** * Start producing results for given context. Provided consumer is notified whenever progress is * made (new value is ready or error occurs). * @param consumer * @param context */ void produceResults(Consumer<T> consumer, ProducerContext context);}
fresco使用了Produer和Consumer的模式。
Producer用于执行各种不同的任务,如网络获取,硬盘缓存,内存缓存,解码等。通过produceResults
方法把结果提供给消费者Consumer,
Consumer处理各种回调事件。
/*** Consumes data produced by {@link Producer}.<T>** <p> The producer uses this interface to notify its client when new data is ready or an error* occurs. Execution of the image request is structured as a sequence of Producers. Each one* consumes data produced by producer preceding it in the sequence.** <p>For example decode is a producer that consumes data produced by the disk cache get producer.** <p> The consumer is passed new intermediate results via onNewResult(isLast = false) method. Each* consumer should expect that one of the following methods will be called exactly once, as the very* last producer call:* <ul>* <li> onNewResult(isLast = true) if producer finishes successfully with a final result </li>* <li> onFailure if producer failed to produce a final result </li>* <li> onCancellation if producer was cancelled before a final result could be created </li>* </ul>** <p> Implementations of this interface must be thread safe, as callback methods might be called* on different threads.** @param <T>*/public interface Consumer<T> { /** * Called by a producer whenever new data is produced. This method should not throw an exception. * * <p> In case when result is closeable resource producer will close it after onNewResult returns. * Consumer needs to make copy of it if the resource must be accessed after that. Fortunately, * with CloseableReferences, that should not impose too much overhead. * * @param newResult * @param isLast true if newResult is the last result */ void onNewResult(T newResult, boolean isLast); /** * Called by a producer whenever it terminates further work due to Throwable being thrown. This * method should not throw an exception. * * @param t */ void onFailure(Throwable t); /** * Called by a producer whenever it is cancelled and won't produce any more results */ void onCancellation(); /** * Called when the progress updates. * * @param progress in range [0, 1] */ void onProgressUpdate(float progress);}
- onNewResult(isLast = true) if producer finishes successfully with a final result
- onFailure if producer failed to produce a final result
- onCancellation if producer was cancelled before a final result could be created
Producer成功完成的时候,回调Consumer的onNewResult方法;失败时回调onFailure方法;取消的话,回调onCancellation方法。
Consumer有一个base实现类BaseConsumer,对异常状况进行了封装处理:
/** * Base implementation of Consumer that implements error handling conforming to the * Consumer's contract. * * <p> This class also prevents execution of callbacks if one of final methods was called before: * onFinish(isLast = true), onFailure or onCancellation. * * <p> All callbacks are executed within a synchronized block, so that clients can act as if all * callbacks are called on single thread. * * @param <T> */@ThreadSafepublic abstract class BaseConsumer<T> implements Consumer<T> { /** * Set to true when onNewResult(isLast = true), onFailure or onCancellation is called. Further * calls to any of the 3 methods are not propagated */ private boolean mIsFinished; public BaseConsumer() { mIsFinished = false; } @Override public synchronized void onNewResult(@Nullable T newResult, boolean isLast) { if (mIsFinished) { return; } mIsFinished = isLast; try { onNewResultImpl(newResult, isLast); } catch (Exception e) { onUnhandledException(e); } } @Override public synchronized void onFailure(Throwable t) { if (mIsFinished) { return; } mIsFinished = true; try { onFailureImpl(t); } catch (Exception e) { onUnhandledException(e); } } @Override public synchronized void onCancellation() { if (mIsFinished) { return; } mIsFinished = true; try { onCancellationImpl(); } catch (Exception e) { onUnhandledException(e); } } /** * Called when the progress updates. * * @param progress in range [0, 1] */ @Override public synchronized void onProgressUpdate(float progress) { if (mIsFinished) { return; } try { onProgressUpdateImpl(progress); } catch (Exception e) { onUnhandledException(e); } } /** * Called by onNewResult, override this method instead. */ protected abstract void onNewResultImpl(T newResult, boolean isLast); /** * Called by onFailure, override this method instead */ protected abstract void onFailureImpl(Throwable t); /** * Called by onCancellation, override this method instead */ protected abstract void onCancellationImpl(); /** * Called when the progress updates */ protected void onProgressUpdateImpl(float progress) { } /** * Called whenever onNewResultImpl or onFailureImpl throw an exception */ protected void onUnhandledException(Exception e) { FLog.wtf(this.getClass(), "unhandled exception", e); }}
BaseConsumer暴露出几个抽象方法:onNewResultImpl,onFailureImpl,onCancellationImpl,onProgressUpdateImpl在不同的时机被调用。
Producer模式,在Fresco中请求产生这块,用到了大量的这种概念,将网络数据的获取,磁盘缓存获取,内存缓存获取,解码,编码和图片的变换等等的处理,分为模块处理,并以倒叙的方式联合再一起调用。显得格外的高大上,就是初次见有点难以理解。
public interface Producer {
void produceResults(Consumer consumer, ProducerContext context);
}
Producer作为一个行为,表示的是生产结果。有了结果就要处理,而produceResults()方法就代表处理结果,那么是谁处理结果我们不知道,所以就由参数传入,故而就有了消费者Consumer。
而Producer的处理模式在Fresco中表现的也比较奇特,由于网络数据的获取,磁盘缓存获取,内存缓存获取,解码,编码和图片等这些操作是一个流程处理,那么如何将流程性的东西和Producer结合起来呢?
为了成为一个链式,会有如下的代码模式:
public class XXProducer implements Producer { private final Producer mInputProducer; public XXProducer (Producer inputProducer) { mInputProducer = inputProducer; } @Override public void produceResults(Consumer consumer, ProducerContext context) { ....//首先执行自己的业务逻辑,如果不满足要求,再往上传递,执行mInputProducer的逻辑 mInputProducer.produceResults(consumer, context); }}
接收一个外部的生产者,并在自身处理结果方法的最后调用外部生产者处理结果的方法。
这样看似先创建外部的生产者,但是实际上最后才调用外部的生产者。所以Fresco实例的创建和反向调用就好像这个样子:
2.mProducerSequenceFactory.getDecodedImageProducerSequence
首先看一下mProducerSequenceFactory 的由来:(ImagePipeline.java)
private final ProducerSequenceFactory mProducerSequenceFactory;public ImagePipeline( ProducerSequenceFactory producerSequenceFactory, Set<RequestListener> requestListeners, Supplier<Boolean> isPrefetchEnabledSupplier, MemoryCache<CacheKey, CloseableImage> bitmapMemoryCache, MemoryCache<CacheKey, PooledByteBuffer> encodedMemoryCache, BufferedDiskCache mainBufferedDiskCache, BufferedDiskCache smallImageBufferedDiskCache, CacheKeyFactory cacheKeyFactory, ThreadHandoffProducerQueue threadHandoffProducerQueue) { mIdCounter = new AtomicLong(); mProducerSequenceFactory = producerSequenceFactory; mRequestListener = new ForwardingRequestListener(requestListeners); mIsPrefetchEnabledSupplier = isPrefetchEnabledSupplier; mBitmapMemoryCache = bitmapMemoryCache; mEncodedMemoryCache = encodedMemoryCache; mMainBufferedDiskCache = mainBufferedDiskCache; mSmallImageBufferedDiskCache = smallImageBufferedDiskCache; mCacheKeyFactory = cacheKeyFactory; mThreadHandoffProducerQueue = threadHandoffProducerQueue;}
看一下ImagePipeline构造函数的调用:(ImagePipelineFactory.java)
public ImagePipeline getImagePipeline() { if (mImagePipeline == null) { mImagePipeline = new ImagePipeline( getProducerSequenceFactory(), mConfig.getRequestListeners(), mConfig.getIsPrefetchEnabledSupplier(), getBitmapMemoryCache(), getEncodedMemoryCache(), getMainBufferedDiskCache(), getSmallImageBufferedDiskCache(), mConfig.getCacheKeyFactory(), mThreadHandoffProducerQueue); } return mImagePipeline;}private final ImagePipelineConfig mConfig;private ProducerFactory mProducerFactory;private ProducerSequenceFactory mProducerSequenceFactory;private ProducerSequenceFactory getProducerSequenceFactory() { if (mProducerSequenceFactory == null) { mProducerSequenceFactory = new ProducerSequenceFactory( getProducerFactory(), mConfig.getNetworkFetcher(), mConfig.isResizeAndRotateEnabledForNetwork(), mConfig.isDownsampleEnabled(), mConfig.isWebpSupportEnabled(), mThreadHandoffProducerQueue); } return mProducerSequenceFactory;}private ProducerFactory getProducerFactory() { if (mProducerFactory == null) { mProducerFactory = new ProducerFactory( mConfig.getContext(), mConfig.getPoolFactory().getSmallByteArrayPool(), getImageDecoder(), mConfig.getProgressiveJpegConfig(), mConfig.isDownsampleEnabled(), mConfig.isResizeAndRotateEnabledForNetwork(), mConfig.getExecutorSupplier(), mConfig.getPoolFactory().getPooledByteBufferFactory(), getBitmapMemoryCache(), getEncodedMemoryCache(), getMainBufferedDiskCache(), getSmallImageBufferedDiskCache(), mConfig.getCacheKeyFactory(), getPlatformBitmapFactory(), mConfig.isDecodeFileDescriptorEnabled()); } return mProducerFactory;}
ProducerSequenceFactory提供了创建produer序列的方法
ProducerFactory提供了各种producer的构造方法
Producer用于执行各种不同的任务,如网络获取,硬盘缓存,内存缓存,解码等。
Producer会提供结果给消费者Consumer
回到mProducerSequenceFactory.getDecodedImageProducerSequence
方法实现((ProducerSequenceFactory.java))
/*** Returns a sequence that can be used for a request for a decoded image.** @param imageRequest the request that will be submitted* @return the sequence that should be used to process the request*/public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence( ImageRequest imageRequest) { Producer<CloseableReference<CloseableImage>> pipelineSequence = getBasicDecodedImageSequence(imageRequest); if (imageRequest.getPostprocessor() != null) { return getPostprocessorSequence(pipelineSequence); //图片后处理,暂时不考虑 } else { return pipelineSequence; }}
主要调用是10行的getBasicDecodedImageSequence
方法,12行的getPostprocessorSequence
暂时不研究
ProducerSequence的执行顺序:
BitmapMemoryCacheGetProducer 只读内存缓存的producer
ThreadHandoffProducer 启动线程的producer,后续的producer都在线程中执行
BitmapMemoryCacheKeyMultiplexProducer 使用memory cache key合并请求的producer
BitmapMemoryCacheProducer 读取内存缓存的producer
DecodeProducer 解码图片的producer,渐进式JPEG图片,gif和webp等动画图片的解码
ResizeAndRotateProducer JPEG图片resizes和rotates处理
AddImageTransformMetaDataProducer 主要包装解码的consumer,并传递到下一个producer
EncodedCacheKeyMultiplexProducer 使用encoded cache key合并请求的producer
EncodedMemoryCacheProducer 读取未解码的内存缓存的producer
DiskCacheProducer 读取磁盘缓存的producer
WebpTranscodeProducer 包装转码WebP到JPEG/PNG的consumer,并传递到下一个producer
NetworkFetchProducer 网络请求的producer
swallow result if prefetch -> bitmap cache get -> background thread hand-off -> multiplex -> bitmap cache -> decode ->
multiplex ->encoded cache -> disk cache -> (webp transcode) -> network fetch
mProducerSequenceFactory.getDecodedImageProducerSequence解析:
1 —>getBasicDecodedImageSequence
2—>getNetworkFetchSequence
2.1 —>newBitmapCacheGetToDecodeSequence() //Bitmap cache get -> thread hand off -> multiplex -> bitmap cache—>decode
2.1.1—>newBitmapCacheGetToBitmapCacheSequence //Bitmap cache get -> thread hand off -> multiplex -> bitmap cache
2.1.1.1—>mProducerFactory.newBitmapMemoryCacheGetProducer //Bitmap cache get
2.1.1.2—>mProducerFactory.newBackgroundThreadHandoffProducer //thread hand off
2.1.1.3—>mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer // multiplex
2.1.1.4—>mProducerFactory.newBitmapMemoryCacheProducer //bitmap cache
2.1.2—> mProducerFactory.newDecodeProducer // decode
2.2—>getCommonNetworkFetchToEncodedMemorySequence() //multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch.
2.2.1—>newEncodedCacheMultiplexToTranscodeSequence ///multiplex -> encoded cache -> disk cache -> (webp transcode)
2.2.1.1—>mProducerFactory.newEncodedCacheKeyMultiplexProducer //multiplex
2.2.1.2—>mProducerFactory.newEncodedMemoryCacheProducer //encoded cache
2.2.1.3—>mProducerFactory.newDiskCacheProducer //disk cache
2.2.1.4—>mProducerFactory.newWebpTranscodeProducer //(webp transcode)
2.2.2—>mProducerFactory.newNetworkFetchProducer //network fetch
首先看下getBasicDecodedImageSequence方法:(ProducerSequenceFactory.java)
private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence( ImageRequest imageRequest) { Preconditions.checkNotNull(imageRequest); Uri uri = imageRequest.getSourceUri(); Preconditions.checkNotNull(uri, "Uri is null."); if (UriUtil.isNetworkUri(uri)) { return getNetworkFetchSequence(); //获取网络sequence } else if (UriUtil.isLocalFileUri(uri)) { if (MediaUtils.isVideo(MediaUtils.extractMime(uri.getPath()))) { return getLocalVideoFileFetchSequence(); } else { return getLocalImageFileFetchSequence(); } } else if (UriUtil.isLocalContentUri(uri)) { return getLocalContentUriFetchSequence(); } else if (UriUtil.isLocalAssetUri(uri)) { return getLocalAssetFetchSequence(); } else if (UriUtil.isLocalResourceUri(uri)) { return getLocalResourceFetchSequence(); } else if (UriUtil.isDataUri(uri)) { return getDataFetchSequence(); } else { String uriString = uri.toString(); if (uriString.length() > 30) { uriString = uriString.substring(0, 30) + "..."; } throw new RuntimeException("Unsupported uri scheme! Uri is: " + uriString); }}
这个方法里,会根据不同的Uri进行不同处理,我们需要关注的是第8行getNetworkFetchSequence
,(ProducerSequenceFactory.java)
/** * swallow result if prefetch -> bitmap cache get -> * background thread hand-off -> multiplex -> bitmap cache -> decode -> multiplex -> * encoded cache -> disk cache -> (webp transcode) -> network fetch. */ private synchronized Producer<CloseableReference<CloseableImage>> getNetworkFetchSequence() { if (mNetworkFetchSequence == null) { mNetworkFetchSequence = newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence()); } return mNetworkFetchSequence; }
这里分为两部分,
1. newBitmapCacheGetToDecodeSequence
( bitmap cache get ->background thread hand-off -> multiplex -> bitmap cache -> decode)
2. getCommonNetworkFetchToEncodedMemorySequence
(multiplex ->encoded cache -> disk cache -> (webp transcode) -> network fetch)
1.newBitmapCacheGetToDecodeSequence
bitmap cache get ->background thread hand-off -> multiplex -> bitmap cache -> decode
/*** Same as {@code newBitmapCacheGetToBitmapCacheSequence} but with an extra DecodeProducer.* @param inputProducer producer providing the input to the decode* @return bitmap cache get to decode sequence*/private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToDecodeSequence( Producer<EncodedImage> inputProducer) { DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer); //decode return newBitmapCacheGetToBitmapCacheSequence(decodeProducer);}
第8行new除了DecodeProducer,这个执行顺序是在newBitmapCacheGetToBitmapCacheSequence
之后的
/** * Bitmap cache get -> thread hand off -> multiplex -> bitmap cache * @param inputProducer producer providing the input to the bitmap cache * @return bitmap cache get to bitmap cache sequence */private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToBitmapCacheSequence( Producer<CloseableReference<CloseableImage>> inputProducer) { BitmapMemoryCacheProducer bitmapMemoryCacheProducer = mProducerFactory.newBitmapMemoryCacheProducer(inputProducer); //bitmap cache BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer = mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer); //multiplex ThreadHandoffProducer<CloseableReference<CloseableImage>> threadHandoffProducer = mProducerFactory.newBackgroundThreadHandoffProducer( //thread hand off bitmapKeyMultiplexProducer, mThreadHandoffProducerQueue); return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer); //Bitmap cache get}
- BitmapMemoryCacheGetProducer 只读内存缓存的producer
- ThreadHandoffProducer 启动线程的producer,后续的producer都在线程中执行
- BitmapMemoryCacheKeyMultiplexProducer 使用memory cache key合并请求的producer
- BitmapMemoryCacheProducer 读取内存缓存的producer
- DecodeProducer 解码图片的producer,渐进式JPEG图片,gif和webp等动画图片的解码
2.getCommonNetworkFetchToEncodedMemorySequence
multiplex ->encoded cache -> disk cache -> (webp transcode) -> network fetch
/*** multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch.*/private synchronized Producer<EncodedImage> getCommonNetworkFetchToEncodedMemorySequence() { if (mCommonNetworkFetchToEncodedMemorySequence == null) { Producer<EncodedImage> inputProducer = newEncodedCacheMultiplexToTranscodeSequence( mProducerFactory.newNetworkFetchProducer(mNetworkFetcher)); //network fetch mCommonNetworkFetchToEncodedMemorySequence = ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer);//AddImageTransformMetaDataProducer 主要包装解码的consumer,并传递到下一个producer if (mResizeAndRotateEnabledForNetwork && !mDownsampleEnabled) { mCommonNetworkFetchToEncodedMemorySequence = mProducerFactory.newResizeAndRotateProducer( mCommonNetworkFetchToEncodedMemorySequence); //ResizeAndRotateProducer JPEG图片resizes和rotates处理 } } return mCommonNetworkFetchToEncodedMemorySequence;}
第8行的mProducerFactory.newNetworkFetchProducer肯定是最后执行的
第7行的newEncodedCacheMultiplexToTranscodeSequence在newNetworkFetchProducer之前执行
第10行和第14行在newEncodedCacheMultiplexToTranscodeSequence之前执行
看一下newEncodedCacheMultiplexToTranscodeSequence的实现:
/** * encoded cache multiplex -> encoded cache -> (disk cache) -> (webp transcode) * @param inputProducer producer providing the input to the transcode * @return encoded cache multiplex to webp transcode sequence */private Producer<EncodedImage> newEncodedCacheMultiplexToTranscodeSequence( Producer<EncodedImage> inputProducer) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && !mWebpSupportEnabled) { inputProducer = mProducerFactory.newWebpTranscodeProducer(inputProducer);//处理webp图片,可选 } inputProducer = mProducerFactory.newDiskCacheProducer(inputProducer);//硬盘缓存producer EncodedMemoryCacheProducer encodedMemoryCacheProducer = mProducerFactory.newEncodedMemoryCacheProducer(inputProducer);//未解码的内存缓存 return mProducerFactory.newEncodedCacheKeyMultiplexProducer(encodedMemoryCacheProducer);//使用encoded cache key合并请求的producer}
ResizeAndRotateProducer JPEG图片resizes和rotates处理
AddImageTransformMetaDataProducer 主要包装解码的consumer,并传递到下一个producer
EncodedCacheKeyMultiplexProducer 使用encoded cache key合并请求的producer
EncodedMemoryCacheProducer 读取未解码的内存缓存的producer
DiskCacheProducer 读取磁盘缓存的producer
WebpTranscodeProducer 包装转码WebP到JPEG/PNG的consumer,并传递到下一个producer
NetworkFetchProducer 网络请求的producer
综上所述,所有的流程,最先执行的肯定是最后创建的producer
1. BitmapMemoryCacheGetProducer 只读内存缓存的mProducerFactory.newBitmapMemoryCacheGetProducer
public BitmapMemoryCacheGetProducer newBitmapMemoryCacheGetProducer( Producer<CloseableReference<CloseableImage>> inputProducer) { return new BitmapMemoryCacheGetProducer(mBitmapMemoryCache, mCacheKeyFactory, inputProducer); }
看一下BitmapMemoryCacheGetProducer这个类:
/** * Bitmap memory cache producer that is read-only. */public class BitmapMemoryCacheGetProducer extends BitmapMemoryCacheProducer { @VisibleForTesting static final String PRODUCER_NAME = "BitmapMemoryCacheGetProducer"; public BitmapMemoryCacheGetProducer( MemoryCache<CacheKey, CloseableImage> memoryCache, CacheKeyFactory cacheKeyFactory, Producer<CloseableReference<CloseableImage>> inputProducer) { super(memoryCache, cacheKeyFactory, inputProducer); } @Override protected Consumer<CloseableReference<CloseableImage>> wrapConsumer( final Consumer<CloseableReference<CloseableImage>> consumer, final CacheKey cacheKey) { // since this cache is read-only, we can pass our consumer directly to the next producer return consumer; } @Override protected String getProducerName() { return PRODUCER_NAME; }}
这个类里没有什么操作,看一下它的父类BitmapMemoryCacheProducer:
public class BitmapMemoryCacheProducer implements Producer<CloseableReference<CloseableImage>> { private final MemoryCache<CacheKey, CloseableImage> mMemoryCache; private final CacheKeyFactory mCacheKeyFactory; private final Producer<CloseableReference<CloseableImage>> mInputProducer;public BitmapMemoryCacheProducer( MemoryCache<CacheKey, CloseableImage> memoryCache, CacheKeyFactory cacheKeyFactory, Producer<CloseableReference<CloseableImage>> inputProducer) { mMemoryCache = memoryCache; mCacheKeyFactory = cacheKeyFactory; mInputProducer = inputProducer;} @Override public void produceResults( final Consumer<CloseableReference<CloseableImage>> consumer, final ProducerContext producerContext) { ... if (producerContext.getLowestPermittedRequestLevel().getValue() >= ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) { listener.onProducerFinishWithSuccess( requestId, getProducerName(), listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null); consumer.onNewResult(null, true); return; } Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(consumer, cacheKey); ……. mInputProducer.produceResults(wrappedConsumer, producerContext);//传递Producer }
produceResults会回调consumer.onNewResult
方法,如果没有取得需要的结果,会依次调用上一层的结果produceResults
。。。。,
注意这里的32行wrapConsumer
,使用了代理模式,每个producer都会调用consumer的方法,但是不同的producer需要在原有consumer的基础上处理自己的一些逻辑,这里呢?就需要将原来的consumer进行代理,调用时,先处理自己的逻辑,然后调用原有consumer的相关方法即可。
有了下一步调用的produceResults()方法,那么哪里才是第一次调用produceResults()的地方呢? 这个地方肯定就是这一系列请求最先开始的地方.另外Consumer是什么时候创建的,怎么处理Producer产生的结果,这里就需要看一下submitFetchRequest方法了。
3.submitFetchRequest
(ImagePipeline.java)
/*** Submits a request for execution and returns a DataSource representing the pending decoded* image(s).* <p>The returned DataSource must be closed once the client has finished with it.* @param imageRequest the request to submit* @return a DataSource representing the pending decoded image(s)*/public DataSource<CloseableReference<CloseableImage>> fetchDecodedImage( ImageRequest imageRequest, Object callerContext) { try { Producer<CloseableReference<CloseableImage>> producerSequence = mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);//这里的Producer肯定就是上边分析的BitmapMemoryCacheProducer return submitFetchRequest( producerSequence, imageRequest, ImageRequest.RequestLevel.FULL_FETCH, callerContext); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); }}private <T> DataSource<CloseableReference<T>> submitFetchRequest( Producer<CloseableReference<T>> producerSequence, ImageRequest imageRequest, ImageRequest.RequestLevel lowestPermittedRequestLevelOnSubmit, Object callerContext) { try { ImageRequest.RequestLevel lowestPermittedRequestLevel = ImageRequest.RequestLevel.getMax( imageRequest.getLowestPermittedRequestLevel(), lowestPermittedRequestLevelOnSubmit); SettableProducerContext settableProducerContext = new SettableProducerContext( imageRequest, generateUniqueFutureId(), mRequestListener, callerContext, lowestPermittedRequestLevel, /* isPrefetch */ false, imageRequest.getProgressiveRenderingEnabled() || !UriUtil.isNetworkUri(imageRequest.getSourceUri()), imageRequest.getPriority()); return CloseableProducerToDataSourceAdapter.create( producerSequence, settableProducerContext, mRequestListener); } catch (Exception exception) { return DataSources.immediateFailedDataSource(exception); }}
这里有个adapter:CloseableProducerToDataSourceAdapter
,看一下这个类:
/*** DataSource<CloseableReference<T>> backed by a Producer<CloseableReference<T>** @param <T>*/@ThreadSafepublic class CloseableProducerToDataSourceAdapter<T extends AbstractProducerToDataSourceAdapter<CloseableReference<T>> { public static <T> DataSource<CloseableReference<T>> create( Producer<CloseableReference<T>> producer, SettableProducerContext settableProducerContext, RequestListener listener) { return new CloseableProducerToDataSourceAdapter<T>( producer, settableProducerContext, listener); } private CloseableProducerToDataSourceAdapter( Producer<CloseableReference<T>> producer, SettableProducerContext settableProducerContext, RequestListener listener) { super(producer, settableProducerContext, listener); } @Override @Nullable public CloseableReference<T> getResult() { return CloseableReference.cloneOrNull(super.getResult()); } @Override protected void closeResult(CloseableReference<T> result) { CloseableReference.closeSafely(result); } @Override protected void onNewResultImpl(CloseableReference<T> result, boolean isLast) { super.onNewResultImpl(CloseableReference.cloneOrNull(result), isLast); }}
这个类有没有很重要的逻辑,只有几个close方法,看一下它的父类AbstractProducerToDataSourceAdapter:
public abstract class AbstractProducerToDataSourceAdapter<T> extends AbstractDataSource<T> {//AbstractDataSource是DataSource的标准实现 private final SettableProducerContext mSettableProducerContext; private final RequestListener mRequestListener; protected AbstractProducerToDataSourceAdapter( Producer<T> producer, SettableProducerContext settableProducerContext, RequestListener requestListener) { mSettableProducerContext = settableProducerContext; mRequestListener = requestListener; mRequestListener.onRequestStart( settableProducerContext.getImageRequest(), mSettableProducerContext.getCallerContext(), mSettableProducerContext.getId(), mSettableProducerContext.isPrefetch()); producer.produceResults(createConsumer(), settableProducerContext); //这里开始首次发送Producer的结果 }// 创建出Consumer private Consumer<T> createConsumer() { return new BaseConsumer<T>() { //BaseConsumer是Consumer的base实现,处理了各种异常情况 @Override protected void onNewResultImpl(@Nullable T newResult, boolean isLast) {//调用当前类的 onNewResultImpl方法 AbstractProducerToDataSourceAdapter.this.onNewResultImpl(newResult, isLast); } @Override protected void onFailureImpl(Throwable throwable) { AbstractProducerToDataSourceAdapter.this.onFailureImpl(throwable); } @Override protected void onCancellationImpl() { AbstractProducerToDataSourceAdapter.this.onCancellationImpl(); } @Override protected void onProgressUpdateImpl(float progress) { AbstractProducerToDataSourceAdapter.this.setProgress(progress); } }; } //consumer的回调 protected void onNewResultImpl(@Nullable T result, boolean isLast) { if (super.setResult(result, isLast)) { if (isLast) { mRequestListener.onRequestSuccess( mSettableProducerContext.getImageRequest(), mSettableProducerContext.getId(), mSettableProducerContext.isPrefetch()); } } } private void onFailureImpl(Throwable throwable) { if (super.setFailure(throwable)) { mRequestListener.onRequestFailure( mSettableProducerContext.getImageRequest(), mSettableProducerContext.getId(), throwable, mSettableProducerContext.isPrefetch()); } } …...}
- AbstractProducerToDataSourceAdapter继承了AbstractDataSource,该类是DataSource的基本实现,说明AbstractProducerToDataSourceAdapter也是一个DataSource
- 构造方法的最后一行,
producer.produceResults(createConsumer(), settableProducerContext
,终于找到了producer的开始位置,这里的producer是由mProducerSequenceFactory.getDecodedImageProducerSequence
的返回值传进来的,这里肯定就是BitmapMemoryCacheGetProducer - 我们知道,Producer produceResults的时候,会回调BaseConsumer的onNewResultImpl方法,在这里的BaseConsumer的匿名实现类中,会回调AbstractProducerToDataSourceAdapter的同名方法,这里关注一下第48行
super.setResult(result, isLast)
,我们看一下super类AbstractDataSource的实现:
/** * Subclasses should invoke this method to set the result to {@code value}. * * <p> This method will return {@code true} if the value was successfully set, or * {@code false} if the data source has already been set, failed or closed. * * <p> If the value was successfully set and {@code isLast} is {@code true}, state of the * data source will be set to {@link AbstractDataSource.DataSourceStatus#SUCCESS}. * * <p> {@link #closeResult} will be called for the previous result if the new value was * successfully set, OR for the new result otherwise. * * <p> This will also notify the subscribers if the value was successfully set. * * <p> Do NOT call this method from a synchronized block as it invokes external code of the * subscribers. * * @param value the value that was the result of the task. * @param isLast whether or not the value is last. * @return true if the value was successfully set. */ protected boolean setResult(@Nullable T value, boolean isLast) { boolean result = setResultInternal(value, isLast); if (result) { notifyDataSubscribers(); } return result; }
notifyDataSubscribers
这正是我们想要的,发送通知给观察者,这里需要注意,需要在setResultInternal返回true时才会通知。看一下notifyDataSubscribers
的实现:
private void notifyDataSubscribers() { final boolean isFailure = hasFailed(); final boolean isCancellation = wasCancelled(); for (Pair<DataSubscriber<T>, Executor> pair : mSubscribers) { notifyDataSubscriber(pair.first, pair.second, isFailure, isCancellation); } } private void notifyDataSubscriber( final DataSubscriber<T> dataSubscriber, final Executor executor, final boolean isFailure, final boolean isCancellation) { executor.execute( new Runnable() { @Override public void run() { if (isFailure) { dataSubscriber.onFailure(AbstractDataSource.this); } else if (isCancellation) { dataSubscriber.onCancellation(AbstractDataSource.this); } else { dataSubscriber.onNewResult(AbstractDataSource.this); } } }); }
这里就是通知观察者的具体实现,成功的话,会回调dataSubscriber的onNewResult方法,这个DataSource是何时订阅的呢?需要回调setController那一步了,在submitRequest时:(AbstractDraweeController.java)
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);
就是这里,我们知道BaseDataSubscriber是DataSubsciber的base实现,成功的话,会回调onNewResultImpl方法,我们注意下11行onNewResultInternal
:
private void onNewResultInternal( String id, DataSource<T> dataSource, @Nullable T image, float progress, boolean isFinished, boolean wasImmediate) { .........//省略 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); } } }
第15行 mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);就是用于显示图片啦。
这样整体的流程就结束了,从setImageUri到图片显示,关于图片显示的逻辑之后再写。
- Fresco解析
- Fresco源码解析 - DraweeView
- fresco解析之Hierarchy
- Fresco解析 (初始化)
- Fresco解析 (Controller)
- Fresco源码解析 - 本地编译
- Fresco解析(DraweeView,DraweeHierarchy)
- Fresco
- Fresco
- Fresco
- fresco
- Fresco
- fresco
- Fresco
- Fresco
- Fresco
- Fresco
- Fresco
- 面试题
- springmvc的前端控制器对css、js等进行过滤
- 归并排序算法
- 虚拟机中的Linux安装VMware Tools的方法
- TensorFlow深度学习,一篇文章就够了
- Fresco解析
- Codevs 1282 约瑟夫问题 线段树
- 就是代替锚点滚动问题总结
- MVVM_Android-CleanArchitecture
- FFmpeg的Android平台移植—编译篇
- 实现一个把十六进制数转换为对应ASCII码的程序
- Spark MLlib — Word2Vec
- Android 手把手带你玩转自定义相机
- hihoCoder挑战赛23Emulator(floyd算法)