原文連接:Glide核心設計一:皮皮蝦,咱們走java
皮皮蝦,又名蝦姑,是淡水中的強者。其頭部的兩個錘節,能夠輕易破壞貝類的外殼,身體上的步足能夠保證快速移動。這些優秀的品質,使它被表情包盯上。android
Glide,做爲Android最優秀的圖片加載框架之一,能和Activity和Fragment的生命週期綁定,是區別於其它網絡框架的核心特徵,也是本文分析的重點。git
咱們將此特徵和皮皮蝦表情包作一個類比:
github
Glide.with(Context).load(String).into(ImageView)可實現從網絡中獲取圖片並展現到ImageView當中。其中和頁面做生命週期綁定的主要入口是Glide.with(Context)。按照通常的分析邏輯應該先分析源碼,才得出結論,但因一入源碼深似海,不利於總體把握,因此先給出結論。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的生命週期作綁定。app
將和生命週期相關的類圖以下(省略大部分類的變量和方法):
框架
以上對各種有一個簡單的瞭解,接下來將重點講清楚各種之間的聯繫。整個生命週期的綁定分爲四部分。ide
根據以上內容可直接跟代碼可跳過如下內容,印象更加深入。函數
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}
`複製代碼
調用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) { //傳入的是Fragment
return get((FragmentActivity) context);
} else if (context instanceof Activity) { //傳入的是Acitivity
return get((Activity) context);
} else if (context instanceof ContextWrapper) { //傳入的是Application
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}複製代碼
以傳入參數爲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(); //獲取FragmentManager
return fragmentGet(activity, fm);
}
}複製代碼
主要調用fragmentGet方法,代碼以下:
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager(); //根據RequestManagerFragment獲取RequestManager,一個RequestManagerFragment包含一個RequestManager
if (requestManager == null) { //若RequestManager爲空,則新建一個而且設置到RequestManagerFragment中
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}複製代碼
getRequestManagerFragment(fm)函數主要是根據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;
}複製代碼
以上就是根據傳入的Context類型建立RequestManager的代碼部分。
添加不可見Fragment的目的,就是由於該Fragment和父類的Activity具備一樣的生命週期,無須改動原有Activity的代碼,便可實現生命週期的監聽。
RequestManagerFragment生命週期相關的代碼以下:
@Override
public void onStart() {
super.onStart();
lifecycle.onStart(); //執行lifecycle的onStart方法
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();//執行lifecycle的onStop方法
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();//執行lifecycle的onDestroy方法
}複製代碼
能夠看出,Fragment的聲明週期的監聽都轉移到類型是ActivityFragmentLifecycle的變量lifecycle中的對應方法執行。查看ActivityFragmentLifecycle的代碼:
void onStart() {
isStarted = true;
//循環set集合lifecycleListeners中全部LifecycleListener,執行對應的onStart
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
//省略onStop()和onDestroy()方法,和onStart()方法相似。複製代碼
set集合的LifecycleListener是如何添加進去的,看ActivityFragmentLifecycle中的代碼:
@Override
public void addListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {//若是當前頁面已經被destroy,則調用對應的onDestroy
listener.onDestroy();
} else if (isStarted) {//若是當前頁面已經開啓,則調用對應的onStart
listener.onStart();
} else { //其餘狀況調用onStop方法
listener.onStop();
}
}複製代碼
addListener(LifecycleListener listener)方法是接口Lifecycle的方法。RequestManagerFragment提供一個公有方法:
ActivityFragmentLifecycle getLifecycle() {
return lifecycle;
}複製代碼
回看第一部分建立RequestManager時:
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());複製代碼
RequestManagerFragment中的Lifecycle做爲RequestManager的構造函數的參數傳遞給RequestManager。RequestManager構造函數以下:
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() {
//在主線程中將當前類實現的LifecycleListener添加到lifecycle中。
lifecycle.addListener(RequestManager.this);
}
});
} else {
//在主線程中將當前類實現的LifecycleListener添加到lifecycle中。
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}複製代碼
因而可知,lifecycle添加的就是RequestManager實現的LifecycleListener接口。
接着查看RequestManager實現LifecycleListener的方法:
@Override
public void onStart() {
// onStart might not be called because this object may be created after the fragment/activity's onStart method.
resumeRequests();
}
@Override
public void onStop() {
pauseRequests();
}
@Override
public void onDestroy() {
requestTracker.clearRequests();
}複製代碼
繼續進入resumeRequests()、pauseRequests()和requestTracker.clearRequests()方法可知,都是調用RequestTracker相應的方法,RequestTracker類包含一個集合的Request,該集合包含一個Activity獲取一個
Fragment的因此圖片請求,將根據RequestManagerFragment的生命週期,統一管理圖片請求。
RequestManager的構造函數有以下方法:
//省略部分代碼...
//監聽網絡變化的類
ConnectivityMonitor connectivityMonitor = factory.build(context,
new RequestManagerConnectivityListener(requestTracker));
//省略部分代碼...
lifecycle.addListener(connectivityMonitor);
//省略部分代碼...複製代碼
以上代碼可看出,ConnectivityMonitor也實現了LifecycleListener。繼續跟蹤代碼發現,factory的實例是ConnectivityMonitorFactory,在該工廠中會檢查網絡權限,同時建立ConnectivityMonitor的實例DefaultConnectivityMonitor。LifecycleListener接口的實現以下:
@Override
public void onStart() {
register(); //register()方法爲註冊廣播監聽網絡變化
}
@Override
public void onStop() {
unregister(); //解除監聽廣播
}
@Override
public void onDestroy() {
// Do nothing.
}複製代碼
廣播接收器代碼以下:
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean wasConnected = isConnected;
isConnected = isConnected(context);
if (wasConnected != isConnected) { //當網絡狀態發生變化時,才調用listener.onConnectivityChanged()方法
listener.onConnectivityChanged(isConnected);
}
}
};複製代碼
ConnectivityListener 的實例的類型是RequestManager的內部類,代碼以下:
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(); //從新開啓圖片請求
}
}
}複製代碼
以上就是Glide實現圖片加載和Activity、Fragment生命週期綁定的所有分析。會發現使用了觀察者模式和工廠模式進行解耦,其中建立一個不可見的Fragment設置到須要被監控生命週期的Activity、Fragment中,最爲精彩。接下來將分析Glide核心設計二:圖片緩存。敬請期待。