聲明:我目前分析的源碼是最新的Glide源碼:4.12.0版本
implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
1. Glide簡介
Glide是一個支持拉取,解碼和展示視頻快照冬筒,圖片,和GIF動畫的框架憎蛤,正如它的名字翻譯一樣:滑翔。讓用戶加載任何形式的圖片列表盡可能地變得更快而柑、更平滑寻馏。
Glide 使用簡明靈活的流式語法API,允許你在大部分情況下一行代碼搞定需求:
Glide.with(fragment)
.load(url)
.into(imageView);
默認(rèn)情況下杖爽,Glide使用的是一個定制化的基于HttpUrlConnection
的棧,但同時也提供了與Google Volley和Square OkHttp快速集成的工具庫。
2. 性能
Glide 充分考慮了Android圖片加載性能的兩個關(guān)鍵方面:
圖片解碼速度
解碼圖片帶來的資源壓力
為了讓用戶擁有良好的App使用體驗(yàn)慰安,圖片不僅要快速加載腋寨,而且還不能因?yàn)檫^多的主線程I/O或頻繁的垃圾回收導(dǎo)致頁面的閃爍和抖動現(xiàn)象。Glide使用了多個步驟來確保在Android上加載圖片盡可能的快速和平滑:
- 自動化焕、智能地下采樣(
downsampling
)和緩存(caching
)萄窜,以最小化存儲開銷和解碼次數(shù); - 積極的資源重用撒桨,例如字節(jié)數(shù)組和Bitmap查刻,以最小化昂貴的垃圾回收和堆碎片影響;
- 深度的生命周期集成元莫,以確保僅優(yōu)先處理活躍的Fragment和Activity的請求,并有利于應(yīng)用在必要時釋放資源以避免在后臺時被殺掉蝶押。
3. 源碼分析
關(guān)于Glide的詳細(xì)使用介紹踱蠢,參見前面鏈接即可,但是分析源碼也要有個開始吧棋电,那我們就從最基本的用法入手茎截,Glide最基本的用法就是三段論:with、load和into赶盔。那我們現(xiàn)在就先從with開始企锌。
3.1 生命周期的作用域(1.Application, 2.Activity于未, 3.Fragment)
//com.bumptech.glide.Glide.java
public static RequestManager with(@NonNull Context context) {
// getRetriever(context)返回RequestManagerRetriever撕攒,下面的生命周期關(guān)聯(lián)會用到
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getContext()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
從Glide.with()靜態(tài)方法中,我們可以看到方法可以傳入5個參數(shù):Context烘浦、Activity抖坪、FragmentActivity、Fragment或者View闷叉。按照作用域分擦俐,我們可以把它分成兩類:Application類和非Application類。
- Application類:它的生命周期是全局的握侧,沒有空白Fragment就綁定Activity/Fragment蚯瞧。
- 非Application類,它的生命周期跟隨Activity和Fragment的生命周期品擎,專門有一個空白Fragment綁定Activity/Fragment埋合。
從上面with的重載方法看出都會調(diào)用到getRetriever()方法,他其實(shí)最終就是返回RequestManagerRetriever對象萄传,緊接著饥悴,我們看看RequestManagerRetriever的get方法。這里先分兩個來看:
- Activity、FragmentActivity西设、Fragment和View
- Context
3.1.1 Activity類的get()
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
//如果不是UI線程瓣铣,生命周期劃分到Application
return get(activity.getApplicationContext());
} else if (activity instanceof FragmentActivity) {
return get((FragmentActivity) activity);
} else {
assertNotDestroyed(activity);
frameWaiter.registerSelf(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
// 不管是Activity、FragmentActivity贷揽、Fragment和View的get()棠笑,最終都會調(diào)用到fragmentGet()
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
//最終with返回綁定了代理Fragemnt的RequestManager
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//創(chuàng)建一個沒有UI的空Fragment來監(jiān)控用戶自定義的Activity生命周期
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
//創(chuàng)建Glide實(shí)例
Glide glide = Glide.get(context);
//綁定Glide和空白的Fragemnt
//注意!禽绪!:這里創(chuàng)建RequestManager的時候會傳入Lifecycle,后面會根據(jù)這個lifecycle來透傳fragment的生命周期給Glide
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
if (isParentVisible) {
requestManager.onStart();
}
current.setRequestManager(requestManager);
}
return requestManager;
}
3.1.2 Context類的get()
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)) {
// 如果在UI線程蓖救,并且是3.1.1小節(jié)的組件,就調(diào)用Activity類的get()印屁,返回綁定了空Fragment的requestManager
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
// 作用域是Application返回的返回綁定了空Fragment的requestManager
return getApplicationManager(context);
}
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) {
//生命周期和Application一致
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
3.1.3 小結(jié)
Glide的with()生命周期總結(jié)如下圖
- 子線程中Glide調(diào)用get()循捺、傳入ApplicationContext和ServiceContext,對應(yīng)的生命周期屬于Application域雄人,生命周期和Application一致
- Activity从橘、Fragment和View對應(yīng)的生命周期是被代理Fragemnt監(jiān)控的,Glide內(nèi)部邏輯會根據(jù)Activity的生命周期做相應(yīng)調(diào)整
3.2 Glide生命周期感知過程
如3.1.1小節(jié)中分析的础钠,不管with傳入的是fragment恰力、Activity還是View,RequestManagerRetriever都會創(chuàng)建一個沒有UI的Fragment(SupportRequestManagerFragment)來當(dāng)代理,當(dāng)用戶自定義的Activity或者Fragment生命周期發(fā)生變化的時候旗吁,Glide內(nèi)部可以通過代理Fragment知道生命周期發(fā)生的變化踩萎,因此內(nèi)部也做相應(yīng)的處理。例如下載并且加載是一個比較耗時操作很钓,如果下載完成之后香府,Activity已經(jīng)被銷毀了,那就不用加載了码倦,所有這就是Glide感知組件生命周期的意義回还,用戶不用主動調(diào)用clear()方法來釋放資源了。關(guān)聯(lián)關(guān)系如下圖叹洲。
3.3 Glide與空Fragment綁定過程
從3.1.3小結(jié)中可以知道柠硕,只有在主線程中調(diào)用with()并且傳入Activity或者Fragment會綁定空Fragment。當(dāng)傳入的activity运提,這個activity上覆蓋的空Fragment是RequestManagerFragment蝗柔;當(dāng)傳入的是fragment,覆蓋在上面的空fragment是SupportRequestManagerFragment民泵。邏輯都是一樣的癣丧,下面以傳入fragment來分析。
/** Pending adds for SupportRequestManagerFragments.
* 空Fragment(SupportRequestManagerFragment)與FragmentManager的映射關(guān)系
*/
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments = new HashMap<>();
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
// 從三個地方去拿空Fragment栈妆,緊接著會分析
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
// 從空Fragment中拿到requestManager
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// 實(shí)例化glide用于在創(chuàng)建requestManager的時候綁定glide
Glide glide = Glide.get(context);
// 創(chuàng)建requestManager并且綁定glide
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//如果父fragment可見胁编,就通知glide的onStart()
if (isParentVisible) {
requestManager.onStart();
}
current.setRequestManager(requestManager);
}
return requestManager;
}
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
// 第一個地方:先從FragmentManager中去拿
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 第二個地方:從內(nèi)存中去拿
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
//以上兩個地方都沒有,就創(chuàng)建一個空Fragment然后返回
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
//記錄映射關(guān)系在內(nèi)存中厢钧,臨時存的
pendingSupportRequestManagerFragments.put(fm, current);
//提交Fragment事務(wù)
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//如果提交成功之后就刪除臨時存的映射關(guān)系
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
從supportFragmentGet()方法中我們看到了Glide內(nèi)部邏輯和空Fragment的綁定過程。
不知道大家有沒有疑惑:為什么在getSupportRequestManagerFragment()方法中要在pendingSupportRequestManagerFragments中臨時保存空Fragment嬉橙?
其實(shí)就是為了避免 SupportRequestManagerFragment 在一個作用域中重復(fù)創(chuàng)建早直。
因?yàn)閏ommitAllowingStateLoss() 是將事務(wù) post 到消息隊(duì)列中的,也就是說市框,事務(wù)是異步處理的霞扬,而不是同步處理的。假設(shè)沒有臨時保存記錄枫振,一旦在事務(wù)異步等待執(zhí)行時調(diào)用了Glide.with(...) 喻圃,就會在該作用域中重復(fù)創(chuàng)建 Fragment。
3.4 生命周期的詳細(xì)監(jiān)聽過程
從上面小節(jié)分析可以看出粪滤,生命周期的管理斧拍,主要對Activity、Fragment和View(實(shí)質(zhì)也是Activity或Fragment)有效杖小,其他的都是Application域肆汹,沒必須分析。所以后面的分析都是基于Activity或者Fragment的生命周期窍侧,而這兩個邏輯都是一樣的县踢,我們還是以Fragment的分析為例转绷。
從前面看出伟件,每個Activity或者Fragment域都會創(chuàng)建一個空Fragment蓋在上面。下來我們就從這個空Fragment開始分析Glide的生命周期是如何受影響的议经。Fragment蓋的空Fragment是SupportRequestManagerFragment.java斧账,那我們就從這里開始。
public class SupportRequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
......
}
從3.1.1小節(jié)可以看到煞肾,創(chuàng)建RequestManager時是通過工廠創(chuàng)建的咧织,那我們在看看這個工廠
//RequestManagerRetriever.java中
//創(chuàng)建Glide實(shí)例
Glide glide = Glide.get(context);
requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//factory接口
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
//默認(rèn)的RequestManager工廠
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);
}
};
RequestManager工廠在創(chuàng)建RequestManager的時候,傳入了glide和lifecycle籍救,在RequestManager中完成綁定习绢。
public class RequestManager
implements ComponentCallbacks2, LifecycleListener,...{
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
......
if (Util.isOnBackgroundThread()) {
Util.postOnUiThread(addSelfToLifecycle);
} else {
//lifecycle的生命周期回調(diào)加入到RequestManager中
lifecycle.addListener(this);
}
......
}
public synchronized void onStart() {
resumeRequests();
// targetTracker維持著Traker列表,每個Traker屬于Glide內(nèi)部需要監(jiān)聽生命周期的邏輯
targetTracker.onStart();
}
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
}
至此,生命周期的詳細(xì)監(jiān)聽過程就通了蝙昙。
總結(jié):調(diào)用with()創(chuàng)建RequestManager闪萄,創(chuàng)建RequestManager傳入Lifecycle對象(這個對象是在無界面 Fragment 中創(chuàng)建的),RequestManager通過Lifecycle通知Glide內(nèi)部的各個業(yè)務(wù)Traker奇颠。
當(dāng) Fragment 的生命周期變化時败去,無界面 Fragment會感知到生命周期變化,然后通過Lifecycle 對象將事件分發(fā)到 RequestManager烈拒,RequestManager的onStart()將事件分發(fā)給targetTracker圆裕,targetTracker分發(fā)給Glide內(nèi)部邏輯广鳍。
參考文檔: