本文透過在位元組面試遇到的問題總結而出,如有不對的地方,請及時批評指正。篇幅較長,請耐心閱讀。如果您想了解其他框架原始碼,歡迎評論區留言!
篇幅較長,請耐心閱讀[玫瑰]
簡介
Glide是一個優秀的圖片載入框架,支援多種資料來源,功能強大,效能高。如圖所示:
使用步驟
1。在build。gradle中新增glide引用
implementation ‘com。github。bumptech。glide:glide:4。12。0’
2。使用glide載入圖片
Glide。with(this)。load(BASE_PIC_URL)。into(img_user)
原始碼分析
設計模式
1。單例模式
Glide使用了單例設計模式,透過雙重校驗鎖機制不僅保證了Glide物件的全域性單例,而且解決了多執行緒環境下的併發安全問題。
2。工廠設計模式
Glide內部的建立RequestManager物件時使用了工廠設計模式,透過定義RequestManagerFactory抽象介面,讓其子類建立RequestManager物件,隱藏其內部建立邏輯。
3。建造者設計模式
Glide使用了靜態類GlideBuilder構建Glide物件,將Glide的各種屬性封裝到GlideBuilder中,根據不同的屬性設定構建不同功能的Glide物件。簡化Glide的構建過程。
生命週期繫結
主執行緒中使用
1
.Glide
使用
With
方法傳入所需要的上下文,主執行緒中一般傳
context
,
fragment
,
activity
來實現對生命週期的繫結。
public static RequestManager with(@NonNull Context context) public static RequestManager with(@NonNull Activity activity) public static RequestManager with(@NonNull Fragment fragment) public static RequestManager with(@NonNull FragmentActivity activity)
2 。下面以
activity
為例,引數傳入activity。
public static RequestManager with(@NonNull Activity activity) { return getRetriever(activity)。get(activity); }
3 。透過呼叫
RequestManagerRetriever
的
get
方法,傳入activity引數返回
RequestManager
物件。
RequestManager
主要負責管理Glide的請求和啟動。
@NonNull public RequestManager get(@NonNull Activity activity) { //判斷是否是後臺執行緒 if (Util。isOnBackgroundThread()) { return get(activity。getApplicationContext()); } else if (activity instanceof FragmentActivity) { return get((FragmentActivity) activity); } else { //判斷當前activity沒有被銷燬,否則丟擲異常 assertNotDestroyed(activity); frameWaiter。registerSelf(activity); //獲取activity中的FragmentManager android。app。FragmentManager fm = activity。getFragmentManager(); //透過fragmentGet方法 ,建立並返回 RequestManager return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } }
RequestManagerRetriever
的
get
方法中根據傳入的引數不同,使用
Util.isOnBackgroundThread
判斷子執行緒和主執行緒分別進行不同的處理。主執行緒中最終都是呼叫
fragmentGet
方法。
注意
,由於這裡的引數是
activity
,獲取的是
fragmentManager
,如果傳入的是
fragment
,則獲取的
childFragmentManager
。
4
.fragmentGet
方法主要是透過
RequestManagerFragment
來獲取
RequestManager
,如果沒有獲取到,則透過
工廠模式
進行建立。同時傳入fragment的
getGlideLifecycle
。
這個lifecycle是重點,需要注意
。
private RequestManager fragmentGet( @NonNull Context context, @NonNull android。app。FragmentManager fm, @Nullable android。app。Fragment parentHint, boolean isParentVisible) { //透過fragmentManager獲取RequestManagerFragment RequestManagerFragment current = getRequestManagerFragment(fm, parentHint); //獲取RequestManagerFragment中的requestManager RequestManager requestManager = current。getRequestManager(); //判斷requestManager if (requestManager == null) { //如果requestManager為空,則透過工廠設計模式創建出requestManager Glide glide = Glide。get(context); requestManager = factory。build( glide, current。getGlideLifecycle(), current。getRequestManagerTreeNode(), context); //如果activity顯示出來,則執行requestManager的onStart方法 if (isParentVisible) { requestManager。onStart(); } current。setRequestManager(requestManager); } return requestManager; }
5 。建立
RequestManagerFragment
,這裡建立一個空白頁面的
RequestManagerFragment
並且繫結到當前activity中。
@NonNull private RequestManagerFragment getRequestManagerFragment( @NonNull final android。app。FragmentManager fm, @Nullable android。app。Fragment parentHint) { //透過tag獲取fragmentManager中儲存的fragment RequestManagerFragment current = (RequestManagerFragment) fm。findFragmentByTag(FRAGMENT_TAG); if (current == null) { //如果獲取不到,則進一步透過 pendingRequestManagerFragments Map中獲取 current = pendingRequestManagerFragments。get(fm); if (current == null) { //如果還是獲取不到,則進行建立 current = new RequestManagerFragment(); current。setParentFragmentHint(parentHint); //同時儲存到map中 pendingRequestManagerFragments。put(fm, current); //然後新增到當前activity中 fm。beginTransaction()。add(current, FRAGMENT_TAG)。commitAllowingStateLoss(); //將這個新增動作透過handler傳送給系統處理 handler。obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm)。sendToTarget(); } } return current; }
6
.RequestManagerFragment
的建構函式建立了
ActivityFragmentLifecycle
用來監聽
RequestManagerFragment
的生命週期
onStart(),onStop(),onDestroy()
。
public SupportRequestManagerFragment() { this(new ActivityFragmentLifecycle()); }public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) { this。lifecycle = lifecycle; } @Override public void onStart() { super。onStart(); lifecycle。onStart(); } @Override public void onStop() { super。onStop(); lifecycle。onStop(); } @Override public void onDestroy() { super。onDestroy(); lifecycle。onDestroy(); }
最後在
fragmentGet方法中
將
ActivityFragmentLifecycle
透過工廠設計模式傳給
RequestManager
並返回。
7
.ActivityFragmentLifecycle繼承於
Lifecycle介面。
@Override public void addListener(@NonNull LifecycleListener listener) { //所有的監聽者都新增監聽 lifecycleListeners。add(listener); //根據不同的生命週期進行處理 if (isDestroyed) { listener。onDestroy(); } else if (isStarted) { listener。onStart(); } else { listener。onStop(); } } @Override public void removeListener(@NonNull LifecycleListener listener) { //移除所有監聽 lifecycleListeners。remove(listener); } void onStart() { //只新增一次監聽 isStarted = true; //同步所有生命週期 for (LifecycleListener lifecycleListener : Util。getSnapshot(lifecycleListeners)) { lifecycleListener。onStart(); } } void onStop() { isStarted = false; //同步所有生命週期 for (LifecycleListener lifecycleListener : Util。getSnapshot(lifecycleListeners)) { lifecycleListener。onStop(); } } void onDestroy() { isDestroyed = true; //同步所有生命週期 for (LifecycleListener lifecycleListener : Util。getSnapshot(lifecycleListeners)) { lifecycleListener。onDestroy(); } }
8
.RequestManager
拿到這個
lifecycle
,進行繫結監聽
RequestManagerFragment
生命週期。
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監聽 lifecycle。addListener(this); } lifecycle。addListener(connectivityMonitor); …………。。 }
9 。透過生命週期的繫結處理對應的業務邏輯和資源釋放等功能。
public synchronized void onStart() { //開始請求 resumeRequests(); targetTracker。onStart(); } @Override public synchronized void onStop() { //開始停止 pauseRequests(); targetTracker。onStop(); } @Override public synchronized void onDestroy() { targetTracker。onDestroy(); //釋放資源 targetTracker。clear(); requestTracker。clearRequests(); lifecycle。removeListener(this); lifecycle。removeListener(connectivityMonitor); Util。removeCallbacksOnUiThread(addSelfToLifecycle); glide。unregisterRequestManager(this); }
總結如下圖所示:
Glide在主執行緒中使用時,透過建立一個空白的fragment新增到當前Activity/Fragment中,用來監聽當前頁面的生命週期變化,進行圖片的顯示或資源的釋放。
子執行緒中使用
1 。 Glide在子執行緒中使用只能傳入applicationContext。
public static RequestManager with(@NonNull Context context)
2 。透過呼叫
RequestManagerRetriever
的
get
方法,傳入activity引數返回
RequestManager
物件。
RequestManager
主要負責管理Glide的請求和啟動。
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)) { 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()); } } //子執行緒返回applicationManager return getApplicationManager(context); }
3 。在
getApplicationManager
方法中透過
雙重校驗鎖
的
單例
方式返回
applicationManager
,applicationManager的建立使用了
工廠設計模式
,隱藏了applicationManager的內部建立細節。
@NonNull private RequestManager getApplicationManager(@NonNull Context context) { if (applicationManager == null) { synchronized (this) { if (applicationManager == null) { Glide glide = Glide。get(context。getApplicationContext()); applicationManager = factory。build( glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context。getApplicationContext()); } } } return applicationManager; }
4
.getApplicationManager建立
applicationManager時傳入了
ApplicationLifecycle
作為生命週期監聽。
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; …………。 //如果是子執行緒,透過使用Handler切換到主執行緒 if (Util。isOnBackgroundThread()) { Util。postOnUiThread(addSelfToLifecycle); } else { lifecycle。addListener(this); } …………。。。。 }
5
.RequestManager
拿到這個
lifecycle
,使用Handler切換到主執行緒進行繫結監聽Application生命週期。
private final Runnable addSelfToLifecycle = new Runnable() { @Override public void run() { lifecycle。addListener(RequestManager。this); } };
6 。透過繫結
Application的onStart()
方法進行請求處理。
public synchronized void onStart() { //開始請求 resumeRequests(); targetTracker。onStart(); }
總結如下圖所示:
當Glide在子執行緒中使用時,只需要監聽application的onStart方法進行業務請求的處理,application銷燬時,整個應用程式都會被銷燬,Glide也會跟隨著應用銷燬而進行資源釋放。所以在子執行緒中使用,由於傳入的context是applicationContext,Glide的生命週期也會和整個應用程式一樣。
以上就是位元組面試後總結的幾個要點,還不會的同學趕緊學起來吧,感謝您的閱讀,創造不易,如果您覺得本篇文章對您有幫助,
請點選關注小編
,您的支援就是小編創作的最大動力!