深入主流框架源碼,有利于思維拓展,以及遇到問題能究其根本,所以今天就來扒一扒Glide的基本主線。
Glide框架之所有受歡迎,一是因為它的加載支持生命周期管理,二是支持gif加載,三是占用內(nèi)存小(默認配置圖片編碼格式為rgb565),內(nèi)部使用了多級緩存。但是目前也發(fā)現(xiàn)有缺點,實際應(yīng)用中發(fā)現(xiàn)對于gif的支持不是特別好,有時候幀數(shù)會出一些問題。
慣例,先說依賴配置:implementation'com.github.bumptech.glide:glide:4.7.1'
以下是基本使用代碼,先看看Glide.with()方法都干了些啥
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
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 get(context).getRequestManagerRetriever();
}
@NonNull
public static Glide get(@NonNull Context context) {
if (glide ==null) {
Class var1 = Glide.class;
? ? ? ? synchronized(Glide.class) {
if (glide ==null) {
checkAndInitializeGlide(context);
? ? ? ? ? ? }
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(), use the provided Glide instance instead");
? ? }else {
isInitializing =true;
? ? ? ? initializeGlide(context);
? ? ? ? isInitializing =false;
? ? }
}
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
//以上非關(guān)鍵代碼注釋
Glide glide = builder.build(applicationContext);
? ? //以下非關(guān)鍵代碼注釋
? ? Glide.glide = glide;
}
從以上調(diào)用鏈可以看出,with方法在Glide的initializeGlide中,創(chuàng)建了Glide類中的靜態(tài)單例對象glide,然后with方法里面第一個函數(shù)getRetriever(activity)返回的是一個RequestManagerRetriever,這個是啥,暫時先不管,解析來看調(diào)用的第二個函數(shù),RequestManagerRetriever的get方法。這里會調(diào)用supportFragmentGet方法,
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return this.get(activity.getApplicationContext());
? ? }else {
assertNotDestroyed(activity);
? ? ? ? androidx.fragment.app.FragmentManager fm = activity.getSupportFragmentManager();
? ? ? ? return this.supportFragmentGet(activity, fm, (Fragment)null, isActivityVisible(activity));
? ? }
}
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull androidx.fragment.app.FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current =this.getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
? ? RequestManager requestManager = current.getRequestManager();
? ? if (requestManager ==null) {
Glide glide = Glide.get(context);
? ? ? ? requestManager =this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
? ? ? ? current.setRequestManager(requestManager);
? ? }
return requestManager;
}
從RequestManagerRetriever#supportFragmentGet這個方法以及函數(shù)內(nèi)部調(diào)用的第一個方法getSupportRequestManagerFragment可以看出,這里創(chuàng)建了一個SupportRequestManagerFragment,并且添加到了activity,并且在這里綁定了一個RequestManager,這2個玩意,其實就是Glide能根據(jù)生命周期管理請求的關(guān)鍵東東,后面會說。
到這里先總結(jié)一下,Glide.with做了幾件事情:
1. 實例化了Glide對象
2.創(chuàng)建了一個名為SupportRequestManagerFragment的無UI的Fragment,與我們的activity進行關(guān)聯(lián),并且為SupportRequestManagerFragment設(shè)置了一個名為RequestManager的對象
--------------------------------------------------------------------------------------------
接下來再看load方法,load方法構(gòu)建了一個RequestBuilder,暫時先不看,我們先看下一個方法,也就是into(設(shè)置到某個Imageview)上,看源碼
@NonNull
public ViewTargetinto(@NonNull ImageView view) {
//上面是一些請求配置項,暫不看
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
? ? ? /*targetListener=*/ null,
? ? ? requestOptions);
}
private <Y extends Target<TranscodeType>>Y into(
@NonNull Y target,
? ? @Nullable RequestListener<TranscodeType> targetListener,
? ? @NonNull RequestOptions options) {
//省略。。。
//這里buildRequest構(gòu)建了一個Request對象,深入追蹤會發(fā)現(xiàn),實際創(chuàng)建的是一個叫做SingleRequest的對象,由于代碼調(diào)用比較深,這里就不一一貼出來了
? Request request = buildRequest(target, targetListener, options);
?//省略。。。
//這里是關(guān)鍵方法,這里調(diào)用了RequestManager的track方法,內(nèi)部調(diào)用了RequestTracker的runRequest方法傳進去的就是剛才構(gòu)建的Request(實際是SingleRequest)
??requestManager.track(target, request);
? return target;
}
下面我們看下RequestTracker類的runRequest干了些啥。。。
public void runRequest(@NonNull Request request) {
requests.add(request);
? if (!isPaused) {
request.begin();
? }else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
? ? }
pendingRequests.add(request);
? }
}
RequestTracker這個類,看到里面管理了2個集合,一個是requests,一個是pendingRequests,有沒有感覺似曾相識的感覺,沒錯,okhttp內(nèi)部也有自己維護的隊列(運行中隊列,待執(zhí)行隊列),不過這里是的維護方式是有區(qū)別的,我們后面說。這里runRequest方法,把singleRequet添加到了requests集合中,判斷如果isPaused,則調(diào)用Request的begin方法,否則添加到pendingRequests中,這里isPaused猜測應(yīng)該是跟頁面生命周期相關(guān)的字段,看下isPause的字段都在哪些地方有賦值,{pauseRequests,pauseAllRequests,resumeRequests},看下這些方法都是在哪些地方有調(diào)用
發(fā)現(xiàn)沒有,又回到了RequestManager的這個類來了,剛才我們說到了,Glide創(chuàng)建的無UI的SupportRequestManagerFragment,里面也塞了一個RequestManger,這里是不是可以認為Glide的生命周期維護是有Activity傳遞給SupportRequestManagerFragment,SupportRequestManagerFragment再傳遞給RequestManager呢?看一下RequestManager的繼承實現(xiàn)關(guān)系,實現(xiàn)了LifecycleListener接口,然后在SupportRequestManagerFragment這個Fragment類中尋找相關(guān)線索,發(fā)現(xiàn)創(chuàng)建的時候有個ActivityFragmentLifecycle這個玩意,這個玩意在SupportRequestManagerFragment的onStart/onStop/onDestory中都有調(diào)用,但是這個東西跟我們的RequestManager有什么關(guān)系呢?我們最終不是調(diào)用的是它嗎,繼續(xù)查看ActivityFragmentLifecycle,發(fā)現(xiàn)它有個addListener方法,看下它的調(diào)用地方,發(fā)現(xiàn)了什么,原來在RequestManager構(gòu)建的時候就把它自己丟給了ActivityFragmentLifecycle,是不是現(xiàn)在一瞬間就清晰了。Activity的生命周期變化傳遞給了SupportRequestManagerFragment,SupportRequestManagerFragment將變化傳遞給了ActivityFragmentLifecycle,ActivityFragmentLifecycle將變化最終給到了RequestManager,然后RequestManager最終調(diào)用到了RequestTracker的resumeRequests/pauseRequests。
剛才上面提到過Glide的RequestTracker里面維護的2個集合跟Okhttp中Dispatcher所處理的方式不一樣,Okhttp是任務(wù)執(zhí)行完后會執(zhí)行finish方法,判斷運行中隊列個數(shù)以及待執(zhí)行隊列的情況,進行任務(wù)轉(zhuǎn)移,而Glide是在頁面onStop的時候直接就把所有的請求都給停止了,然后在onStart的時候,把那些沒有完成或者失敗的請求再次開始請求。
上面只提到了Glide的調(diào)用鏈,基本思路,以及生命周期的管理如何實現(xiàn),但是最終的請求,我們還沒有追蹤到,就是SingleRequest的begin方法,這個方法后面的邏輯涉及到后面的多級緩存以及相求相關(guān),這里簡單梳理一下
SignleRequest#begin()->SignleRequest#onSizeReady(overrideWidth, overrideHeight); ? ? -> engine.load(***)這個方法里面涉及到緩存讀取(loadFromActiveResources/loadFromCache),由于時間關(guān)系,凌晨一點多了,后面邏輯有時間再補充,白天上班擼碼,晚上還要回來學習復習鞏固知識,時間有點不夠用