本文通過在位元組面試遇到的問題總結而出,如有不對的地方,請及時批評指正。篇幅較長,請耐心閱讀。如果您想了解其他架構源碼,歡迎評論區留言!
篇幅較長,請耐心閱讀[玫瑰]
簡介
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的生命周期也會和整個應用程式一樣。
以上就是位元組面試後總結的幾個要點,還不會的同學趕緊學起來吧,感謝您的閱讀,創造不易,如果您覺得本篇文章對您有幫助,請點選關注小編,您的支援就是小編創作的最大動力!