簡述
Glide爲Android平臺下的圖片加載框架,它的使用方法可以查看教程文檔。
這裏從一個最簡單的使用實例入手,分析glide源碼調用過程(使用的glide版本爲v4.8.0):
Glide.with(activity)
.load(imgUrl)
.into(imageView);
本例實現了在一個FragmentActivity中,加載遠程圖片,顯示在imageview視圖上。圖片加載過程大致可以分爲三步:
- with: 預備開啓一個加載,並與當前Activity生命週期綁定;
- load:設置數據源,構建請求的參數;
- into:創建請求,開始真正的加載圖片,最終顯示在視圖上。
接下來從第一步with方法開始,看看源碼中做了什麼操作。
源碼分析
with方法中主要做了兩件事,一是初始化Glide對象,二是返回合適的RequestManager對象。
Glide初始化
在Glide類中,有多個with方法的重載實現,最終都是返回RequestManager對象,(RequestManager負責管理髮起的加載Request),如圖:
簡單概括它們的作用是當傳入的上下文爲FragmentActivity或者可以取到FragmentActivity時,可以將本次加載與FragmentActivity的生命週期進行綁定,其中又分別適配了v4和app的FragmentManager。
在本例中將會調用下面的重載方法:
@NonNull
publicstatic RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
其中getRetriever方法返回RequestManagerRetriever(顧名思義,它負責創建或檢索出合適的RequestManager)。
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
看Glide.get(context)方法,返回單例:
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
checkAndInitializeGlide方法中加了一個boolean變量判斷避免重複調用初始化,其中又調用initializeGlide方法。
接下來就是Glide的初始化過程:
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
@SuppressWarnings("deprecation")
privatestatic void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
// 獲取註解生成的自定義的GlideModule,具體使用查看Glide文檔「Generated API」說明。
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
// 獲取在AndroidManifest中註冊的GlideModule(Glide V4之前的版本使用)。
manifestModules = new ManifestParser(applicationContext).parse();
}
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
// 排除不需要的GlideModule(由自己決定)。
com.bumptech.glide.module.GlideModule current = iterator.next();
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
// 獲取自定義的RequestManagerFactory,設置給GlideBuilder。
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
// 可以在自定義的GlideModule中給GlideBuilder設置配置。
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
// 可以在自定義的GlideModule中給GlideBuilder設置配置。
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
// 通過GlideBuilder構造了一個Glide對象。
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
// 可以在自定義的GlideModule中給glide中的Registry添加或替換組件。
module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {
// 可以在自定義的GlideModule中給glide中的Registry添加或替換組件。
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
// 註冊ComponentCallbacks2用以監聽內存使用情況。
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
在本例中使用默認的glide配置,沒有自定義GlideModule,直接看builder.build(applicationContext)方法:
@NonNull
Glide build(@NonNull Context context) {
// 初始化用於網絡操作的線程池。
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 初始化用於磁盤緩存操作的線程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 初始化用於動畫的線程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
// 初始化根據手機設備推薦緩存容器大小的計算輔助工具類
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
// 初始化生成網絡監聽廣播註冊的工廠類,該Factory會根據是否有NETWORK_PERMISSION生成對應的監聽器(通常情況下都應該申請)。擁有權限情況下的監聽器會註冊廣播監聽CONNECTIVITY_ACTION,當收到聯網廣播時會觸發RequestManager嘗試重試請求。
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
// 初始化bitmap緩存容器
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
// 初始化存儲字節數組的緩存容器
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
// 初始化Resource緩存容器
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
// 初始化用於創建磁盤緩存的工廠類
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 初始化引擎,該對象負責啓動加載資源和管理活動和緩存的資源。重要的類,後續加載和處理響應都會經過此類。
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
// 初始化獲取RequestManager的工具類,接下來馬上就會用到。
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
// 最終創建並返回Glide對象
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
GlideBuilder的build方法中初始化了多個線程池對應不同使用功能,便於不同模塊的線程管理,以及緩存容器和Engine、RequestManagerRetriever對象。之後實例化Glide對象並傳入各個參數。
接着看Glide的構造方法:
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
final Resources resources = context.getResources();
registry = new Registry();
// Right now we're only using this parser for HEIF images, which are only supported on OMR1+.
// If we need this for other file types, we should consider removing this restriction.
// Note that order here matters. We want to check the ExifInterface parser first for orientation
// and then fall back to DefaultImageHeaderParser for other fields.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
registry.register(new DefaultImageHeaderParser());
···
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
···
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
···
.append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance())
.append(
Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
.append(Bitmap.class, bitmapEncoder)
···
.register(new ByteBufferRewinder.Factory())
···
.register(
Bitmap.class,
BitmapDrawable.class,
new BitmapDrawableTranscoder(resources))
···
;
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
engine,
logLevel);
}
這裏主要做了三件事:
1.保存在GlideBuilder中完成初始化的對象;
2.初始化Registry對象,該對象中註冊了一系列資源轉換和編解碼的工具類,後續流程會從中查找對應的工具類去解析和處理資源;
3.初始化GlideContext對象,該對象繼承自ContextWrapper,後續的流程中會通過它獲取註冊表和引擎等加載資源所需的對象。
以上完成了Glide對象的創建和初始化。回到Glide的getRetriever方法中,這裏將返回RequestManagerRetriever對象,接下來是通過它獲取RequestManager對象。
RequestManager獲取
RequestManagerRetriever類的get方法也有多個重載:
with方法需要多個重載主要是因爲這裏,這裏根據參數類型查找FragmentManager,利用它實現和當前activity的生命週期綁定。
先看get(Context):
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
根據context的類型再調用相應的get方法。若當前非主線程或上下文是Application,直接調用getApplicationManager方法(這種情況下不會綁定生命週期)。
不進行生命週期綁定的RequestManager
當在子線程調用with方法,或傳入上下文爲application時,會通過getApplicationManager方法返回RequestManager對象:
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
// ApplicationLifecycle實現Lifecycle接口,用於跟蹤和通知Application的生命週期事件。
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
該方法會返回一個單例的RequestManager對象,通過工廠模式創建,factory在RequestManagerRetriever實例化時候賦值,默認爲DEFAULT_FACTORY:
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
可以看到build方法直接new了一個RequestManager對象,接着看看RequestManager的構造方法:
public RequestManager(
@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),
glide.getConnectivityMonitorFactory(),
context);
}
// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
// requestTracker用於跟蹤、取消和重新啓動進行中、已完成和失敗的請求。
this.requestTracker = requestTracker;
this.context = context;
// 創建網絡連接監聽器,當網絡恢復可用時會通過requestTracker嘗試重啓請求。
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
// 在主線程添加LifecycleListener到Lifecycle中
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
// 將自身保存到glide的managers成員變量中(managers爲一個ArrayList)。
glide.registerRequestManager(this);
}
這裏的lifecycle爲ApplicationLifecycle,它的addListener方法只是通知新的監聽器已啓動。
與當前Activity進行生命週期綁定的RequestManager
get的其他重載方法都是試圖獲取到FragmentManager,然後調用supportFragmentGet方法或者fragmentGet方法查找或創建RequestManager對象。
(ps:fragmentGet方法適配android.app.FragmentManager,已棄用)
這裏以get(FragmentActivity)爲例:
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
// 獲取FragmentManager
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
關鍵在supportFragmentGet方法:
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
// 查找SupportRequestManagerFragment對象,它就是一個Fragment
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
// 從SupportRequestManagerFragment中獲取requestManager
RequestManager requestManager = current.getRequestManager();
// 若不存在則創建,之後保存在SupportRequestManagerFragment中
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
// 這裏創建RequestManager時傳入了ActivityFragmentLifecycle
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
該方法中會通過getSupportRequestManagerFragment方法獲取一個Fragment,返回其中的RequestManager,若不存在則新建一個,並保存在Fragment中。
接着看getSupportRequestManagerFragment方法:
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
// 通過tag查找當前頁面中的指定Fragment
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 獲取已創建但等待往當前頁面添加的Fragment,避免fm add fragment期間重複創建
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
// 初始化SupportRequestManagerFragment
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
// 保存到集合中避免重複創建
pendingSupportRequestManagerFragments.put(fm, current);
// 將SupportRequestManagerFragment添加到當前頁面中
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
// 在handler的handleMessage中會將上面保存的從集合中移除
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
這裏可以看出,Glide是通過往當前頁面添加一個Fragment,藉助Fragment的生命週期來通知RequestManager,來實現綁定管理。
SupportRequestManagerFragment和RequestManager之間是通過ActivityFragmentLifecycle來實現生命週期回調:
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
在supportFragmentGet方法中創建RequestManager時,會傳入SupportRequestManagerFragment的lifecycle成員變量:
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
而在RequestManager的構造方法中,又會向這個lifecycle中註冊LifecycleListener接口的實現類即RequestManager自身:
if (Util.isOnBackgroundThread()) {
// 發送到主線程添加
mainHandler.post(addSelfToLifecycle);
} else {
// 添加自身,RequestManager實現了LifecycleListener接口
lifecycle.addListener(this);
}
// 添加網絡監聽器
lifecycle.addListener(connectivityMonitor);
因此實現了綁定關係:
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
unregisterFragmentWithRoot();
}
在Fragment的生命週期回調方法中調用lifecycle的對應方法,而lifecycle中又會調用LifecycleListener接口的相應方法,即RequestManager的onStart、onStop、onDestroy方法。
總結
Glide的with方法會初始化Glide單例對象,並完成一系列默認和自定義配置。之後通過它的requestManagerRetriever成員變量查找創建返回RequestManager對象,後續會通過這個RequestManager進行資源請求的管理。在獲取RequestManager的過程中,會通過往當前頁面添加一個Fragment,來實現RequestManager和頁面生命週期綁定。