默認(rèn)情況下,Glide會在開始一個新的圖片請求(網(wǎng)絡(luò)請求)之前檢查以下多級緩存
1. 活動資源 (Active Resources)
2. 內(nèi)存緩存 (Memory Cache)
3. 資源類型(Resource Disk Cache)
4. 原始數(shù)據(jù) (Data Disk Cache)
活動資源:如果當(dāng)前對應(yīng)的圖片資源正在使用,則這個圖片會被Glide放入活動緩存。
內(nèi)存緩存:如果圖片最近被加載過,并且當(dāng)前沒有使用這個圖片,則會被放入內(nèi)存中
資源類型: 被解碼后的圖片寫入磁盤文件中,解碼的過程可能修改了圖片的參數(shù)(如:inSampleSize、inPreferredConfig)數(shù)據(jù))
原始數(shù)據(jù): 圖片原始數(shù)據(jù)在磁盤中的緩存(從網(wǎng)絡(luò)、文件中直接獲得的原始
在調(diào)用Glide.with(activity) .load(url) .into(imageView)時,Glide會首先從Active Resources查找當(dāng)前是否有對應(yīng)的活躍圖片,沒有則查找內(nèi)存緩存,沒有則查找資源類型,沒有則查找原始數(shù)據(jù)。

第一層 活動資源
活動資源是一個“引用計數(shù)”的圖片資源的弱引用集合。
因為同一張圖片可能在多個地方被同時使用,每一次使用都會將引用計數(shù)+1,而當(dāng)引用計數(shù)為0時候,則表示這個圖片沒有被使用也就是沒有強(qiáng)引用了。這樣則會將圖片從活動資源中移除,并加入內(nèi)存緩存。
/**
* 引用計數(shù)為0回調(diào)
* 將其從正在使用集合移除 并加入內(nèi)存緩存
* @param key
* @param resource
*/
@Override
public void onResourceReleased(Key key, Resource resource) {
activeResource.deactivete(key);
Glide.get(context).getBitmapPool().put(resource.getBitmap());
}
第二層 內(nèi)存緩存
內(nèi)存緩存默認(rèn)使用LRU(最近最少使用算法),當(dāng)資源從活動資源移除的時候,會加入此緩存。使用圖片的時候會主動從此緩存移除,加入活動資源。
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
} else {
this.maxSize = maxSize;
this.map = new LinkedHashMap(0, 0.75F, true);
}
}
LinkedHashMap的第三個參數(shù)為true,開啟自動排序,在使用此map進(jìn)行g(shù)et或者put的時候會自動排序,確保了最近最少使用的在尾端最先被刪除。
第三,四層 磁盤緩存
Resource緩存的是經(jīng)過解碼后的圖片。
Data緩存的則是圖像原始數(shù)據(jù)。同樣都是維護(hù)了一個LRU的算法
Bitmap復(fù)用
如果緩存都不存在,那么會從源地址獲得圖片(網(wǎng)絡(luò)/文件)。而在解析圖片的時候會需要BitmapPool(復(fù)用池),達(dá)到復(fù)用的效果


復(fù)用效果如上。在未使用復(fù)用的情況下,每張圖片都需要一塊內(nèi)存。而使用復(fù)用的時候,如果存在能被復(fù)用的圖片會重復(fù)使用該圖片的內(nèi)存。
所以復(fù)用并不能減少程序正在使用的內(nèi)存大小。Bitmap復(fù)用,解決的是減少頻繁申請內(nèi)存帶來的性能(抖動、碎片)問題。
BitmapPool是Glide中的Bitmap復(fù)用池,同樣適用LRU來進(jìn)行管理。
當(dāng)一個Bitmap從內(nèi)存緩存 被動 的被移除(內(nèi)存緊張、達(dá)到maxSize)的時候并不會被recycle。而是加入這個BitmapPool,只有從這個BitmapPool 被動被移除的時候,Bitmap的內(nèi)存才會真正被recycle釋放。
網(wǎng)絡(luò)加載
資源來源可能有url網(wǎng)絡(luò)下載,也可能是sd卡中資源加載。根據(jù)來源不同來分別使用對應(yīng)的方式進(jìn)行加載最終獲取得到inputstream流,再通過解碼器解碼inputstream來得到Bitmap。采用了策略模式,工廠模式,建造者模式根據(jù)不同的URI來生產(chǎn)對應(yīng)的加載器。解析出來的圖片資源會存入磁盤緩存,然后再存入到活動資源中!
生命周期管理
Glide生命周期綁定是從入口單例類Glide開始的,通過with()多個重載方法來實現(xiàn)對生命周期的綁定工作。
public static RequestManager with(Fragment fragment)
public static RequestManager with(FragmentActivity activity)
public static RequestManager with(Activity activity)
public static RequestManager with(Context context)
以Activity的參數(shù)為例:
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
RequestManagerRetriever是一個單例類,可以理解為一個工廠類,通過get方法接收不同的參數(shù),來創(chuàng)建RequestManager。
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm);
}
}
public RequestManager get(android.app.Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return get(fragment.getActivity().getApplicationContext());
} else {
android.app.FragmentManager fm = fragment.getChildFragmentManager();
return fragmentGet(fragment.getActivity(), fm);
}
}
如果是在子線程進(jìn)行的with操作,那么Glide將默認(rèn)使用ApplicationContext,可以理解為不對請求的生命周期進(jìn)行管理,通過Activity拿到FragmentManager,并將創(chuàng)建RequestManager的任務(wù)傳遞下去。最終都走到了fragmentGet方法,注意細(xì)微區(qū)別是Activity傳的參數(shù)的是Activity的FragmentManager,F(xiàn)ragment傳的參數(shù)的是ChildFragmentManager,這兩者不是一個東西。
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
//獲取RequestManagerFragment,并獲取綁定到這個fragment的RequestManager
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
//如果獲取RequestManagerFragment還沒有綁定過RequestManager,那么就創(chuàng)建RequestManager并綁定到RequestManagerFragment
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
創(chuàng)建RequestManagerFragment
這個方法創(chuàng)建了一個fragment,并且創(chuàng)建并綁定了一個RequestManager,看看getRequestManagerFragment如何獲取的RequestManagerFragment。
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
//嘗試根據(jù)id去找到此前創(chuàng)建的RequestManagerFragment
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//如果沒有找到,那么從臨時存儲中尋找
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
//如果仍然沒有找到,那么新建一個RequestManagerFragment,并添加到臨時存儲中。
//然后開啟事務(wù)綁定fragment并使用handler發(fā)送消息來將臨時存儲的fragment移除。
current = new RequestManagerFragment();
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
接著往下看RequestManagerFragment的構(gòu)造方法做了什么。
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
直接創(chuàng)建一個ActivityFragmentLifecycle,這個類實際是一個生命周期回調(diào)的管理類,實現(xiàn)了Lifecycle接口。所有的LifecycleListener會添加到一個集合中,當(dāng)RequestManagerFragment生命周期方法觸發(fā)時,會調(diào)用ActivityFragmentLifecycle相應(yīng)生命周期方法,這個方法然后再遍歷調(diào)用所有LifecycleListener的生命周期方法,以onStart生命周期方法為例,RequestManagerFragment中:
public void onStart() {
super.onStart();
lifecycle.onStart();
}
然后ActivityFragmentLifecycle中:
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
rootRequestManagerFragment
RequestManagerFragment還有一個rootRequestManagerFragment的成員變量,Glide每創(chuàng)建一個RequestManagerFragment,都會嘗試實例化rootRequestManagerFragment,這個fragment即頂級的Activity所創(chuàng)建的RequestManagerFragment,相關(guān)代碼:
public void onAttach(Activity activity) {
super.onAttach(activity);
rootRequestManagerFragment = RequestManagerRetriever.get()
.getRequestManagerFragment(getActivity().getFragmentManager());
if (rootRequestManagerFragment != this) {
rootRequestManagerFragment.addChildRequestManagerFragment(this);
}
}
@Override
public void onDetach() {
super.onDetach();
if (rootRequestManagerFragment != null) {
rootRequestManagerFragment.removeChildRequestManagerFragment(this);
rootRequestManagerFragment = null;
}
}
可以看到,不管當(dāng)前的RequestManagerFragment是通過何種方式創(chuàng)建的,都會在OnAttach時,拿到當(dāng)前所綁定的Activity的FragmentManager來初始化一個RequestManagerFragment,這個RequestManagerFragment有可能是自身,有可能已經(jīng)被初始化過了,比如是通過with(Activity activity)的方式初始化的,那么很顯然
RequestManagerRetriever.get().getRequestManagerFragment(getActivity().getFragmentManager());
這句代碼拿到的會是自己本身,而如果是通過with(Fragment fragment)的形式創(chuàng)建的,rootRequestManagerFragment將指向當(dāng)前fragment綁定到Activity所綁定的RequestManagerFragment,如果該Activity沒有綁定過,那么會開啟事務(wù)綁定一個RequestManagerFragment。并且如果自己不是rootRequestManagerFragment的話,那么將會把自己保存到rootRequestManagerFragment中的一個集合:
private void addChildRequestManagerFragment(RequestManagerFragment child) {
childRequestManagerFragments.add(child);
}
簡而言之,Glide會為Activity創(chuàng)建一個RequestManagerFragment做為rootFragment,并保存該Activity底下所有Fragment(如果有的話)所創(chuàng)建的RequestManagerFragment。
RequestManagerTreeNode
RequestManagerFragment初始化時,還會初始化RequestManagerTreeNode,顧名思義,這個類是用來保存請求樹節(jié)點的,比如一個Activity采用Viewpager + Fragment的形式,而里面的Fragment又是一個ViewPager + Fragment的形式,這個時候,假設(shè)其中一個RequestManagerFragment生命周期方法走了,怎么知道哪些RequestManagerFragment綁定的LifeCycle應(yīng)該得到調(diào)用呢?理想的情況是,應(yīng)該讓綁定該RequestManagerFragment的Fragment所有的子Fragment的RequestManagerFragment的生命周期得到調(diào)用,比如如下場景中,Activity中各有兩個Fragment,兩個Fragment又各有兩個子Fragment,在所有Fragment中,均通過with(this)的方式來加載圖片,經(jīng)過之前的分析我們可以知道的是,ROOT RMF 中會保存有6個RMF(RMF即RequestManagerFragment):

當(dāng)如果F1 RMF生命周期做出反應(yīng)時,因為RequestManagerFragment是無界面的,所以可以理解為F1的生命周期做出反應(yīng)。我們希望F11和F12所綁定的RequestManagerFragment也要立即做出反應(yīng)。但是F2以及其底下的RequestManagerFragment則不應(yīng)響應(yīng)對應(yīng)生命周期事件,我們知道任何一個RequestManagerFragment可以通過rootRequestManagerFragment拿到這6個RMF,繼而拿到其所對應(yīng)的RequestManager,那么怎么去確定F11 RMF 和 F12 RMF呢?這就是RequestManagerTreeNode干的事情了,RequestManagerFragment中的非靜態(tài)內(nèi)部類FragmentRequestManagerTreeNode實現(xiàn)了RequestManagerTreeNode:
private class FragmentRequestManagerTreeNode implements RequestManagerTreeNode {
@Override
public Set<RequestManager> getDescendants() {
Set<RequestManagerFragment> descendantFragments = getDescendantRequestManagerFragments();
HashSet<RequestManager> descendants =
new HashSet<RequestManager>(descendantFragments.size());
for (RequestManagerFragment fragment : descendantFragments) {
if (fragment.getRequestManager() != null) {
descendants.add(fragment.getRequestManager());
}
}
return descendants;
}
}
這個類做的事情比較簡單,調(diào)用外部類RequestManagerFragment的方法getDescendantRequestManagerFragments拿到所有的“后裔”Fragment,然后再取出它的RequestManager,然后集合裝起來返回,這里的后裔在前面的例子中,指的就是F11 RMF 和 F12 RMF,看看getDescendantRequestManagerFragments是怎么拿到的F11和F12:
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public Set<RequestManagerFragment> getDescendantRequestManagerFragments() {
//如果自己是rootFragment,那么直接返回childRequestManagerFragments
if (rootRequestManagerFragment == this) {
return Collections.unmodifiableSet(childRequestManagerFragments);
} else if (rootRequestManagerFragment == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
// Pre JB MR1 doesn't allow us to get the parent fragment so we can't introspect hierarchy, so just
// return an empty set.
return Collections.emptySet();
} else {
HashSet<RequestManagerFragment> descendants = new HashSet<RequestManagerFragment>();
for (RequestManagerFragment fragment
//遍歷取出rootFragment中的RMF,并獲取到其parentFragment,找出后裔。
: rootRequestManagerFragment.getDescendantRequestManagerFragments()) {
if (isDescendant(fragment.getParentFragment())) {
descendants.add(fragment);
}
}
return Collections.unmodifiableSet(descendants);
}
}
RequestManager
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
//獲取RequestManagerFragment,并獲取綁定到這個fragment的RequestManager
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
//如果獲取RequestManagerFragment還沒有綁定過RequestManager,那么就創(chuàng)建RequestManager并綁定到RequestManagerFragment
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
RequestManager是一個非常核心的類,并且還實現(xiàn)了LifecycleListener來處理請求的生命周期。上述代碼在創(chuàng)建RequestManager時,傳遞了3個參數(shù),分別是context,前面分析過的初始化RequestManagerFragment所創(chuàng)建的LifeCycle和RequestManagerTreeNode。直接看RequestManager的構(gòu)造函數(shù):
public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
}
調(diào)用的另一個構(gòu)造方法,并增加了兩個新的參數(shù)RequestTracker和ConnectivityMonitorFactory。
RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext();
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.glide = Glide.get(context);
this.optionsApplier = new OptionsApplier();
ConnectivityMonitor connectivityMonitor = factory.build(context,
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.
if (Util.isOnBackgroundThread()) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
});
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}
RequestTracker即所有請求操作的真正處理者,所有Request的暫停取消執(zhí)行操作都由RequestTracker來完成,如RequestManager暫停請求的實現(xiàn):
public void pauseRequests() {
Util.assertMainThread();
requestTracker.pauseRequests();
}
生命周期回調(diào)總結(jié)
在RequestManager構(gòu)造方法中,還會將自身添加到LifeCycle中,這樣,整個流程就暢通了

1.調(diào)用時通過Glide.with傳入context,利用context構(gòu)建一個Fragment
2.監(jiān)聽Fragment生命周期,銷毀時釋放Glide資源
Glide源碼分析流程圖

項目代碼:
https://github.com/games2sven/Glide
本文轉(zhuǎn)自作者“十年開發(fā)程序員”的Glide生命周期管理,如有侵權(quán),請聯(lián)系作者效效進(jìn)行修改。