本文是Glide源碼解析系列的第一篇,通過這篇文檔按厘,將可以了解到:
- 1.Glide如何綁定Activity抵恋、Fragment生命周期。
- 2.Glide如何監(jiān)聽內(nèi)存變化挠日、網(wǎng)絡(luò)變化疮绷。
- 3.Glide如何處理請求的生命周期。
1.0 生命周期相關(guān)UML類圖
2.0 生命周期綁定
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);
}
}
如果是在子線程進行的with操作计技,那么Glide將默認使用ApplicationContext喜德,可以理解為不對請求的生命周期進行管理住诸,通過Activity拿到FragmentManager奄薇,并將創(chuàng)建RequestManager的任務(wù)傳遞下去沫屡。最終都走到了fragmentGet方法金矛,注意細微區(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;
}
2.0.1 創(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;
}
這里有個問題,為什么需要使用pendingRequestManagerFragments這樣一個集合來臨時存儲一下fragment牢酵,然后又馬上通過handler發(fā)送消息移除悬包?這其實是跟主線程的Looper機制和Fragment的事務(wù)機制有關(guān)的(點擊這里查看Fragment事務(wù)流程分析)。我們知道馍乙,android中的主線程是一個閉環(huán)布近,通過Handler發(fā)送消息到MessageQueue,然后通過Looper輪詢獲取消息并交給Handler處理(點擊這里查看Activity啟動流程分析)丝格。如下面一個常見場景:
Glide.with(this).load(url_1).into(mImageView_1);
Glide.with(this).load(url_2).into(mImageView_2);
這段代碼通過Glide加載了兩張圖片并設(shè)置到了兩個ImageView上撑瞧,當(dāng)以上代碼塊執(zhí)行時,其所屬的代碼群的Message剛剛從MessageQueue中取出正在被處理显蝌,我們假設(shè)這個Message為m1预伺,并且這個MessageQueue中沒有其他消息。此時情形是這樣的:
當(dāng)代碼執(zhí)行到getRequestManagerFragment這個方法時曼尊,會通過開啟事務(wù)的方式來綁定這個fragment到activity酬诀,相關(guān)源碼如下(有興趣了解的點擊這里查看Fragment事務(wù)流程分析),這個方法在FragmentManagerImpl.java中:
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
這里的mHost其實就是activity創(chuàng)建的骆撇,并且持有activity以及mMainHandler的引用瞒御,根據(jù)上述代碼可以知道,其實綁定fragment的操作最終是通過主線程的handler發(fā)送消息處理的神郊,我們假設(shè)這個消息為m2肴裙。然后handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();這句代碼發(fā)送的消息為m3趾唱。那么當(dāng)Glide.with(this).load(url_1).into(mImageView_1);這句代碼執(zhí)行這里時,消息隊列有了變化:
但是m2這個消息并不會馬上被處理蜻懦,這是因為m1還有代碼還沒有執(zhí)行完畢甜癞,也就是說這個fragment并不會馬上被綁定,此時m1繼續(xù)向下執(zhí)行到第二句代碼Glide.with(this).load(url_2).into(mImageView_2);當(dāng)這句代碼走到getRequestManagerFragment時阻肩,如果在m1時带欢,我們不將fragment臨時存儲在pendingRequestManagerFragments中,由于m2還沒有被處理烤惊,那么
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
必然是找不到這個fragment的乔煞,那么就會導(dǎo)致重新創(chuàng)建一個新的重復(fù)的fragment,并開啟事務(wù)綁定柒室,這顯然是不合情理的渡贾,因為Glide需要保證rootFragment的唯一性,rootFragment即fragment依附或者沒有fragment依附的activity所創(chuàng)建的最上層RequestManagerFragment雄右。
接著往下看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();
}
}
2.0.2 rootRequestManagerFragment
上面UML圖上智厌,可以知道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律罢。
2.0.3 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);
}
}
看看isDescendant方法是如何判斷的:
private boolean isDescendant(Fragment fragment) {
Fragment root = this.getParentFragment();
while (fragment.getParentFragment() != null) {
if (fragment.getParentFragment() == root) {
return true;
}
fragment = fragment.getParentFragment();
}
return false;
}
依上面的例子,當(dāng)遍歷到F11 RMF時锤岸,參數(shù)傳遞過來的是F11竖幔,root 則為F1,F(xiàn)11再拿到parent是偷,也是F1拳氢,返回true,F(xiàn)12 RMF類似也返回true蛋铆;
當(dāng)遍歷到F21 RMF時馋评,參數(shù)傳入F21,root仍是F1戒职,此時F21再怎么拿Parent也不可能是root,返回false栗恩。
簡而言之,RequestManagerTreeNode用來獲取綁定該RequestManagerFragment的Fragment的所有子Fragment所綁定的RequestManagerFragment所綁定的RequestManager
2.0.4 RequestManager
上面一直在說RequestManagerFragment洪燥,下面回到FragmentGet方法中磕秤,再貼一次,免得上翻麻煩:
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;
}
根據(jù)上面的UML圖,可以知道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();
}
2.0.5 網(wǎng)絡(luò)狀態(tài)監(jiān)測
請求生命周期的實現(xiàn)細節(jié)后面再說殖侵,暫時埋坑,先來看看ConnectivityMonitorFactory這個工廠生產(chǎn)了什么镰烧。
public class ConnectivityMonitorFactory {
public ConnectivityMonitor build(Context context, ConnectivityMonitor.ConnectivityListener listener) {
final int res = context.checkCallingOrSelfPermission("android.permission.ACCESS_NETWORK_STATE");
final boolean hasPermission = res == PackageManager.PERMISSION_GRANTED;
if (hasPermission) {
return new DefaultConnectivityMonitor(context, listener);
} else {
return new NullConnectivityMonitor();
}
}
}
很簡單拢军,接收一個ConnectivityListener根據(jù)是否有監(jiān)控網(wǎng)絡(luò)狀態(tài)的權(quán)限來創(chuàng)建相應(yīng)的網(wǎng)絡(luò)監(jiān)控器。
DefaultConnectivityMonitor也比較簡單怔鳖,就是內(nèi)部定義了一個廣播接收者茉唉,并且也實現(xiàn)了lifeCycleListener。在上面RequestManager的構(gòu)造方法中,創(chuàng)建了一個RequestManagerConnectivityListener:
private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {
private final RequestTracker requestTracker;
public RequestManagerConnectivityListener(RequestTracker requestTracker) {
this.requestTracker = requestTracker;
}
@Override
public void onConnectivityChanged(boolean isConnected) {
if (isConnected) {
requestTracker.restartRequests();
}
}
}
這個listener很簡單赌渣,收到網(wǎng)絡(luò)狀態(tài)連接就重啟請求魏铅。然后通過工廠創(chuàng)建出了DefaultConnectivityMonitor昌犹,并把它添加到了lifecycle中坚芜。到這里,Glide監(jiān)測網(wǎng)絡(luò)狀態(tài)來重啟請求的實現(xiàn)方式就呼之欲出了斜姥,大體步驟如下:
在相應(yīng)的生命周期方法中鸿竖,會調(diào)用lifecycle的生命周期方法,lifecycle會調(diào)用DefaultConnectivityMonitor所實現(xiàn)的相應(yīng)生命周期方法來注冊及解除注冊網(wǎng)絡(luò)狀態(tài)的廣播接收者铸敏,收到廣播后缚忧,會回調(diào)之前傳遞的參數(shù)ConnectivityListener的onConnectivityChanged方法來處理Request。
2.0.6 內(nèi)存狀態(tài)監(jiān)測
RequestManager中還存有Glide這個入口類的實例杈笔,構(gòu)造方法中直接獲取到的闪水,用來對內(nèi)存狀態(tài)的變更作出處理,比較簡單蒙具,看看流程便可以了球榆,以onTrimMemory為例,
當(dāng)RequestManagerFragment的onTrimMemory被調(diào)用時,會調(diào)用其綁定的RequetManager的相應(yīng)方法來處理:
@Override
public void onTrimMemory(int level) {
// If an activity is re-created, onTrimMemory may be called before a manager is ever set.
// See #329.
if (requestManager != null) {
requestManager.onTrimMemory(level);
}
}
然后RequestManager再調(diào)用Glide入口類的trimMemory來釋放更多內(nèi)存:
public void onTrimMemory(int level) {
glide.trimMemory(level);
}
2.0.7 生命周期回調(diào)流程總結(jié)
在RequestManager構(gòu)造方法中禁筏,還會將自身添加到LifeCycle中持钉,這樣,整個流程就暢通了:
細心的可以發(fā)現(xiàn)篱昔,雖然在構(gòu)造RequestManager時傳遞了參數(shù)RequestManagerTreeNode每强,但是在這個回調(diào)流程中,并沒有對所有后裔RMF的RequestManager進行調(diào)用州刽,Glide默認確實是不會去調(diào)用空执,但這里并不意味著這些RequestManager不會被調(diào)用到,事實上穗椅,當(dāng)前RMF生命周期被調(diào)用時辨绊,就意味后裔Fragment生命周期也會被調(diào)用,那么后裔Fragment這個流程仍然會走一遍房待,那么RequestManagerTreeNode到底有什么用呢?答案是沒用邢羔,完全沒用,如果只是簡單使用Glide的話桑孩。當(dāng)然拜鹤,RequestManager暴露了相關(guān)接口給開發(fā)者使用:
public void resumeRequestsRecursive() {
Util.assertMainThread();
resumeRequests();
for (RequestManager requestManager : treeNode.getDescendants()) {
requestManager.resumeRequests();
}
}
調(diào)用這個方法將會把所有后裔的請求同時一起處理。