使用Fresco之前,1定先要進行初始化,1般初始化的工作會在Application.onCreate()
完成,固然也能夠在使用Drawee
之前完成。
Fresco本身提供了兩種初始化方式,1種是使用使用默許配置初始化,另外一種是使用用戶自定義配置。
以下代碼是Fresco提供的兩個初始化方法。第1個只需要提供1個Context
參數,第2個還需要提供 ImagePipeline 的配置實例 - ImagePipelineConfig
。
/** Initializes Fresco with the default config. */
public static void initialize(Context context) {
ImagePipelineFactory.initialize(context);
initializeDrawee(context);
}
/** Initializes Fresco with the specified config. */
public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig) {
ImagePipelineFactory.initialize(imagePipelineConfig);
initializeDrawee(context);
}
先來分析1下第1種方式。
Fresco.initialized(context)
com.facebook.drawee.backends.pipeline.Fresco
/** Initializes Fresco with the default config. */
public static void initialize(Context context) {
ImagePipelineFactory.initialize(context);
initializeDrawee(context);
}
其中 ImagePipeline
負責獲得圖象數據,可以是網絡圖片,也能夠是本地圖片。這里用1個 Factory - ImagePipelineFactory
來創建默許的 ImagePipleline
。
com.facebook.imagepipeline.core.ImagePipelineFactory
/** Initializes {@link ImagePipelineFactory} with default config. */
public static void initialize(Context context) {
initialize(ImagePipelineConfig.newBuilder(context).build());
}
ImagePipelineConfig
為ImagePipeline
的初始化工作提供了必須的參數,它的構建進程采取了Builder模式。
ImagePipelineConfig
中包括了很多參數,由于我們調用 Fresco.initialize()
的時候值傳遞了1個 context
參數,所以 Fresco 還沒有獲得任何用戶自定義的數據,因此全部使用默許值,Builder
類只提供了構建的進程,而默許值則需要等到新建 ImagePipelineConfig
時創建。
通過 Builder
的部份源碼可以看出,初始化1個 ImagePipeline
需要很多參數,這些參數的具體意義會在后續的博文中介紹。
public static class Builder {
private Supplier<MemoryCacheParams> mBitmapMemoryCacheParamsSupplier;
private CacheKeyFactory mCacheKeyFactory;
private final Context mContext;
private Supplier<MemoryCacheParams> mEncodedMemoryCacheParamsSupplier;
private ExecutorSupplier mExecutorSupplier;
private ImageCacheStatsTracker mImageCacheStatsTracker;
private ImageDecoder mImageDecoder;
private Supplier<Boolean> mIsPrefetchEnabledSupplier;
private DiskCacheConfig mMainDiskCacheConfig;
private MemoryTrimmableRegistry mMemoryTrimmableRegistry;
private NetworkFetcher mNetworkFetcher;
private PoolFactory mPoolFactory;
private ProgressiveJpegConfig mProgressiveJpegConfig;
private Set<RequestListener> mRequestListeners;
private boolean mResizeAndRotateEnabledForNetwork = true;
private DiskCacheConfig mSmallImageDiskCacheConfig;
private AnimatedImageFactory mAnimatedImageFactory;
// other methods
}
從 Fresco 的 initialize
方法中我們得知,ImagePipelineConfig
是這么創建的:
ImagePipelineConfig.newBuilder(context).build())
而 Builder
并沒有提供參數的默許值,那默許值肯定是在 buid()
方法完成賦值。
com.facebook.imagepipeline.core.ImagePipelineFactory$Builder
public ImagePipelineConfig build() {
return new ImagePipelineConfig(this);
}
由以上代碼可以看出,build()
會創建1個 ImagePipelineConfig
,然后把 this
作為參數傳給構造函數,而ImagePipelineConfig
的構造函數就是根據 Builder
來初始化自己。
初始化的策略非常簡單:
builder
中的參數值為空,則使用默許值。builder
中的參數值不為空,則使用 Builder
提供的值。可以通過1個具體的參數來看1下,如果 builder.mBitmapMemoryCacheParamsSupplier
為空,則 new DefaultBitmapMemoryCacheParamsSupplier()
,如果不空,則使用 builder.mBitmapMemoryCacheParamsSupplier
。
mBitmapMemoryCacheParamsSupplier =
builder.mBitmapMemoryCacheParamsSupplier == null ?
new DefaultBitmapMemoryCacheParamsSupplier(
(ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
builder.mBitmapMemoryCacheParamsSupplier;
最后把這個 build 出來的 ImagePipelineConfig
實例傳給 ImagePipelineFactory
的靜態方法 initialize
,完成初始化。
/** Initializes {@link ImagePipelineFactory} with the specified config. */
public static void initialize(ImagePipelineConfig imagePipelineConfig) {
sInstance = new ImagePipelineFactory(imagePipelineConfig);
}
ImagePipelineFactory
的實例 sInstance
會在初始化 Drawee 的時候用到。
通過以上分析我們了解到,Fresco
會首先初始化 ImagePipeline
,并把ImagePipeline
的實例保存在1個 ImagePipelineFactory
類型的靜態變量中 - sInstance
;然后開始初始化 Drawee
。
private static void initializeDrawee(Context context) {
sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
}
首先,new
1個 PipelineDraweeControllerBuilderSupplier
,它是 PipelineDraweeControllerBuilder
的1個 Supplier
。Supplier
不是由 JDK 提供的,而是 Fresco 直接從 guava 中移過來的,代碼簡單,只提供了1個 get
方法。
/**
* 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();
}
顧名思義,Supplier
是1個提供者,用戶包括但不限于factory
, generator
, builder
, closure
,接口方法 get()
用于返回它所提供的實例,需要注意的是,這個實例可以是新建的,也能夠不是。
在這里,PipelineDraweeControllerBuilderSupplier
的用法更像是1個 Factory
,它實現了 Supplier
接口。
public class PipelineDraweeControllerBuilderSupplier implements
Supplier<PipelineDraweeControllerBuilder> {
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;
}
@Override
public PipelineDraweeControllerBuilder get() {
return new PipelineDraweeControllerBuilder(
mContext,
mPipelineDraweeControllerFactory,
mImagePipeline,
mBoundControllerListeners);
}
}
構造函數 PipelineDraweeControllerBuilderSupplier(Context context)
,使用了在 Fresco
的 initalize
方法中通過 ImagePipelineFactoryBuilder
創建的 ImagePipelineFactory
的實例。
this(context, ImagePipelineFactory.getInstance());
get
方法告知我們,ImagePipeline
會存儲在 PipelineDraweeController
中,關于 Controller
可以參考 Fresco源碼解析 - Hierarachy-View-Controller。
同時 PipelineDraweeController
也會存儲1個 mPipelineDraweeControllerFactory
。
public class PipelineDraweeControllerFactory {
private Resources mResources;
private DeferredReleaser mDeferredReleaser;
private AnimatedDrawableFactory mAnimatedDrawableFactory;
private Executor mUiThreadExecutor;
public PipelineDraweeControllerFactory(
Resources resources,
DeferredReleaser deferredReleaser,
AnimatedDrawableFactory animatedDrawableFactory,
Executor uiThreadExecutor) {
mResources = resources;
mDeferredReleaser = deferredReleaser;
mAnimatedDrawableFactory = animatedDrawableFactory;
mUiThreadExecutor = uiThreadExecutor;
}
public PipelineDraweeController newController(
Supplier<DataSource<CloseableReference<CloseableImage>>> dataSourceSupplier,
String id,
Object callerContext) {
return new PipelineDraweeController(
mResources,
mDeferredReleaser,
mAnimatedDrawableFactory,
mUiThreadExecutor,
dataSourceSupplier,
id,
callerContext);
}
}
這個 mPipelineDraweeControllerFactory
會通過 newController
來創建1個 PipelineDraweeController
的實例。
到底,初始化的工作就完成了。
以上分析雖然簡單,但是清楚地梳理了 Fresco 的初始化進程,不過任然是遠遠不夠的,由以上代碼可以看出,初始化對應組件(Drawee、ImagePipeline)時用到了很多的設計模式,如果不太熟習這些設計模式,可能理解起來會比較費勁。更加關鍵的是,初始化對應的組件用到了大量的參數,每一個參數背后又會牽扯到很多知識點,后續博文中,我們再來逐一分析。