Glide核心设计一:皮皮虾,我们走
原文鏈接:Glide核心設(shè)計一:皮皮蝦,我們走
引言
皮皮蝦,又名蝦姑,是淡水中的強者。其頭部的兩個錘節(jié),可以輕易破壞貝類的外殼,身體上的步足可以保證快速移動。這些優(yōu)秀的品質(zhì),使它被表情包盯上。
Glide,作為Android最優(yōu)秀的圖片加載框架之一,能和Activity和Fragment的生命周期綁定,是區(qū)別于其它網(wǎng)絡(luò)框架的核心特征,也是本文分析的重點。
我們將此特征和皮皮蝦表情包做一個類比:
圖片網(wǎng)絡(luò)請求緊跟Activity、Fragment的生命周期,當(dāng)頁面不可交互時自動停止加載,當(dāng)回到可交互狀態(tài)時,繼續(xù)加載。就像表情包(Activity、Fragment)控制皮皮蝦(圖片請求)一樣。
框架設(shè)計
簡單使用
Glide.with(Context).load(String).into(ImageView)可實現(xiàn)從網(wǎng)絡(luò)中獲取圖片并展示到ImageView當(dāng)中。其中和頁面作生命周期綁定的主要入口是Glide.with(Context)。按照一般的分析邏輯應(yīng)該先分析源碼,才得出結(jié)論,但因一入源碼深似海,不利于整體把握,所以先給出結(jié)論。Glide.with(Context)返回的是一個RequestManager,我們來看RequestManager的類的說明注釋。
A class for managing and starting requests for Glide. Can use activity, fragment and connectivity lifecycle events to intelligently stop, start, and restart requests. Retrieve either by instantiating a new object, or to take advantage built in Activity and Fragment lifecycle handling, use the static Glide.load methods with your Fragment or Activity.
由此可知,該類就是用于將請求和Activity或Framgent的生命周期做綁定。
類圖
將和生命周期相關(guān)的類圖如下(省略大部分類的變量和方法):
類的簡單介紹
類的聯(lián)系
以上對各類有一個簡單的了解,接下來將重點講清楚各類之間的聯(lián)系。整個生命周期的綁定分為四部分。
代碼解讀
根據(jù)以上內(nèi)容可直接跟代碼可跳過以下內(nèi)容,印象更加深刻。
第一部分:Glide.with(Context)
public static RequestManager with(Context context) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(context);} `復(fù)制代碼調(diào)用RequestManagerRetriever的get方法如下:
public RequestManager get(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) { //傳入的是Fragmentreturn get((FragmentActivity) context);} else if (context instanceof Activity) { //傳入的是Acitivityreturn get((Activity) context);} else if (context instanceof ContextWrapper) { //傳入的是Applicationreturn get(((ContextWrapper) context).getBaseContext());}}return getApplicationManager(context);}復(fù)制代碼以傳入?yún)?shù)為Activity類型為例,代碼如下:
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(); //獲取FragmentManagerreturn fragmentGet(activity, fm); }}復(fù)制代碼主要調(diào)用fragmentGet方法,代碼如下:
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {RequestManagerFragment current = getRequestManagerFragment(fm); RequestManager requestManager = current.getRequestManager(); //根據(jù)RequestManagerFragment獲取RequestManager,一個RequestManagerFragment包含一個RequestManagerif (requestManager == null) { //若RequestManager為空,則新建一個并且設(shè)置到RequestManagerFragment中requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());current.setRequestManager(requestManager);}return requestManager;}復(fù)制代碼getRequestManagerFragment(fm)函數(shù)主要是根據(jù)FragmentManager獲取Fragment,代碼如下:
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); //通過Tag查找if (current == null) { //若為空,從緩存pendingRequestManagerFragments中查找current = pendingRequestManagerFragments.get(fm);if (current == null) { //緩存中也不存在,則新建一個RequestManagerFragment,并且添加到頁面中。current = new RequestManagerFragment();pendingRequestManagerFragments.put(fm, current);fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();}}return current;}復(fù)制代碼以上就是根據(jù)傳入的Context類型創(chuàng)建RequestManager的代碼部分。
第二部分:監(jiān)聽不可見Fragment的生命周期并傳遞給RequestManager
添加不可見Fragment的目的,就是因為該Fragment和父類的Activity具有同樣的生命周期,無須改動原有Activity的代碼,即可實現(xiàn)生命周期的監(jiān)聽。
RequestManagerFragment生命周期相關(guān)的代碼如下:
可以看出,Fragment的聲明周期的監(jiān)聽都轉(zhuǎn)移到類型是ActivityFragmentLifecycle的變量lifecycle中的對應(yīng)方法執(zhí)行。查看ActivityFragmentLifecycle的代碼:
void onStart() {isStarted = true;//循環(huán)set集合lifecycleListeners中所有LifecycleListener,執(zhí)行對應(yīng)的onStartfor (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {lifecycleListener.onStart();}}//省略onStop()和onDestroy()方法,和onStart()方法類似。復(fù)制代碼set集合的LifecycleListener是如何添加進(jìn)去的,看ActivityFragmentLifecycle中的代碼:
public void addListener(LifecycleListener listener) {lifecycleListeners.add(listener);if (isDestroyed) {//如果當(dāng)前頁面已經(jīng)被destroy,則調(diào)用對應(yīng)的onDestroylistener.onDestroy();} else if (isStarted) {//如果當(dāng)前頁面已經(jīng)開啟,則調(diào)用對應(yīng)的onStartlistener.onStart();} else { //其他情況調(diào)用onStop方法listener.onStop();}}復(fù)制代碼addListener(LifecycleListener listener)方法是接口Lifecycle的方法。RequestManagerFragment提供一個公有方法:
ActivityFragmentLifecycle getLifecycle() {return lifecycle;}復(fù)制代碼回看第一部分創(chuàng)建RequestManager時:
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());復(fù)制代碼RequestManagerFragment中的Lifecycle作為RequestManager的構(gòu)造函數(shù)的參數(shù)傳遞給RequestManager。RequestManager構(gòu)造函數(shù)如下:
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();//監(jiān)聽網(wǎng)絡(luò)變化的類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() {public void run() {//在主線程中將當(dāng)前類實現(xiàn)的LifecycleListener添加到lifecycle中。lifecycle.addListener(RequestManager.this);}});} else {//在主線程中將當(dāng)前類實現(xiàn)的LifecycleListener添加到lifecycle中。lifecycle.addListener(this);}lifecycle.addListener(connectivityMonitor);}復(fù)制代碼由此可見,lifecycle添加的就是RequestManager實現(xiàn)的LifecycleListener接口。
第三部分:RequestManager實現(xiàn)LifecycleListener
接著查看RequestManager實現(xiàn)LifecycleListener的方法:
public void onStart() {// onStart might not be called because this object may be created after the fragment/activity's onStart method.resumeRequests();}public void onStop() {pauseRequests();}public void onDestroy() {requestTracker.clearRequests();}復(fù)制代碼繼續(xù)進(jìn)入resumeRequests()、pauseRequests()和requestTracker.clearRequests()方法可知,都是調(diào)用RequestTracker相應(yīng)的方法,RequestTracker類包含一個集合的Request,該集合包含一個Activity獲取一個
Fragment的所以圖片請求,將根據(jù)RequestManagerFragment的生命周期,統(tǒng)一管理圖片請求。
第四部分:監(jiān)聽網(wǎng)絡(luò)狀態(tài)并作出相應(yīng)
RequestManager的構(gòu)造函數(shù)有如下方法:
//省略部分代碼...//監(jiān)聽網(wǎng)絡(luò)變化的類ConnectivityMonitor connectivityMonitor = factory.build(context,new RequestManagerConnectivityListener(requestTracker));//省略部分代碼...lifecycle.addListener(connectivityMonitor); //省略部分代碼...復(fù)制代碼以上代碼可看出,ConnectivityMonitor也實現(xiàn)了LifecycleListener。繼續(xù)跟蹤代碼發(fā)現(xiàn),factory的實例是ConnectivityMonitorFactory,在該工廠中會檢查網(wǎng)絡(luò)權(quán)限,同時創(chuàng)建ConnectivityMonitor的實例DefaultConnectivityMonitor。LifecycleListener接口的實現(xiàn)如下:
public void onStart() {register(); //register()方法為注冊廣播監(jiān)聽網(wǎng)絡(luò)變化}public void onStop() {unregister(); //解除監(jiān)聽廣播}public void onDestroy() {// Do nothing.}復(fù)制代碼廣播接收器代碼如下:
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {boolean wasConnected = isConnected;isConnected = isConnected(context);if (wasConnected != isConnected) { //當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生變化時,才調(diào)用listener.onConnectivityChanged()方法listener.onConnectivityChanged(isConnected);}}};復(fù)制代碼ConnectivityListener 的實例的類型是RequestManager的內(nèi)部類,代碼如下:
private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {private final RequestTracker requestTracker;public RequestManagerConnectivityListener(RequestTracker requestTracker) {this.requestTracker = requestTracker;}public void onConnectivityChanged(boolean isConnected) {if (isConnected) { //如果當(dāng)前狀態(tài)是鏈接狀態(tài)requestTracker.restartRequests(); //重新開啟圖片請求}}}復(fù)制代碼小結(jié)
以上就是Glide實現(xiàn)圖片加載和Activity、Fragment生命周期綁定的全部分析。會發(fā)現(xiàn)使用了觀察者模式和工廠模式進(jìn)行解耦,其中創(chuàng)建一個不可見的Fragment設(shè)置到需要被監(jiān)控生命周期的Activity、Fragment中,最為精彩。接下來將分析Glide核心設(shè)計二:圖片緩存。敬請期待。
轉(zhuǎn)載于:https://juejin.im/post/58abfbe95c497d005f732e0d
總結(jié)
以上是生活随笔為你收集整理的Glide核心设计一:皮皮虾,我们走的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从一道面试题,到“我可能看了假源码[2]
- 下一篇: RTEMS移植USB无线网卡的设想