Glide 生命週期管理
作者:靈魂攻城獅
鏈接:https://www.jianshu.com/p/190285e18ae1
Glide 生命週期管理
1.Glide 特點
-
使用簡單
-
可配置度高,自適應程度高
-
支持常見圖片格式(jpg、png、gif、webp)
-
支持多種數據源(網絡、本地、資源、Assets 等)
-
高效緩存策略(支持 Memory 和 Disk 圖片緩存,默認 Bitmap 格式採用 RGB_565 內存小)
-
生命週期集成(根據 Activity/Fragment 生命週期自動管理請求)
-
高效處理 Bitmap(使用 BitmapPool 複用 Bitmap,主動調用 recycle 回收需要回收的 Bitmap)
2.Glide 使用攻略
Glide.with(this)
// .asBitmap()//只允許加載靜態圖片,若傳入gif圖會展示第一幀(要在load之前)
// .asGif()//指定gif格式(要在load之前)
// .asDrawable()//指定drawable格式(要在load之前)
.load(imageUrl)//被加載圖像的url地址
.placeholder(R.drawable.ic\_placeholder)//佔位圖片
.error(R.drawable.ic\_error)//錯誤圖片
.transition(GenericTransitionOptions.with(R.anim.zoom\_in))//圖片動畫
.override(800,800)//設置加載尺寸
.skipMemoryCache(true)//禁用內存緩存功能
.diskCacheStrategy(DiskCacheStrategy.NONE)//不緩存任何內容
// .diskCacheStrategy(DiskCacheStrategy.DATA)//只緩存原始圖片
// .diskCacheStrategy(DiskCacheStrategy.RESOURCE)//只緩存轉換後的圖片
// .diskCacheStrategy(DiskCacheStrategy.ALL)//緩存所有
// .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)//Glide根據圖片資源智能地選擇使用哪一種緩存策略(默認)
.listener(new RequestListener<Drawable>() {//監聽圖片加載狀態
//圖片加載完成
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
//圖片加載失敗
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.into(imageView);//圖片最終要展示的地方
3.Glide 生命週期原理分析
Glide.with(this)
with 方法可以接受 Context,Activity,FragmentActivity,Fragment 和 View 不同的類型。
private static volatile Glide glide;
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
**雙重檢測單例模式(DCL)**保證 Glide 對象的唯一性,get 方法裏面初始化了 Glide,通過建造者模式創建了一個 GlideBuilder 對象(資源請求線程池,本地緩存加載線程池,動畫線程池,內存緩存器,磁盤緩存工具等等)。
構造完 RequestManagerRetriever 通過 get 返回一個 RequestManager(以 Activity 爲例)
//通過Activity拿到RequestManager
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
//如果是子線程就用Application級別的context,也就是不進行生命週期管理
return get(activity.getApplicationContext());
} else {
//檢查Activity是否銷燬
assertNotDestroyed(activity)
//拿到當前Activity的FragmentManager
android.app.FragmentManager fm = activity.getFragmentManager();
//生成一個Fragment去綁定一個請求管理RequestManager
return fragmentGet(
activity, fm, /\*parentHint=\*/ null, isActivityVisible(activity));
}
}
如果當前線程是子線程,則不需要對 Glide 生命週期進行管理,否則通過 fragmentGet 函數創建一個 fragment:
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//①在當前Activity添加一個Fragment用於管理請求的生命週期
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//獲取RequestManager
RequestManager requestManager = current.getRequestManager();
//如果不存在RequestManager,則創建
if (requestManager == null) {
Glide glide = Glide.get(context);
//②構建RequestManager
//current.getGlideLifecycle()就是ActivityFragmentLifecycle,也就是構建RequestManager時會傳入fragment中的ActivityFragmentLifecycle
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//將構建出來的RequestManager綁定到fragment中
current.setRequestManager(requestManager);
}
//返回當前請求的管理者
return requestManager;
}
①Fragment 與 Activity 的綁定—>getRequestManagerFragment:
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//通過TAG拿到已經實例化過的fragment(也就是同一個Activity Glide.with多次,沒必要創建多個fragment)
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT\_TAG);
if (current == null) {
//如果當前Activity中沒有拿到管理生命週期的fragment,那就從緩存取
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
//如果緩存也沒有,直接new一個
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
//執行請求
current.getGlideLifecycle().onStart();
}
//添加到Map緩存中(防止fragment重複創建)
pendingRequestManagerFragments.put(fm, current);
//將fragment綁定到activity
fm.beginTransaction().add(current, FRAGMENT\_TAG).commitAllowingStateLoss();
//添加後發送清理緩存
handler.obtainMessage(ID\_REMOVE\_FRAGMENT\_MANAGER, fm).sendToTarget();
}
}
return current;
}
②構建 RequestManager 並設置監聽
//此工廠就是爲了構建出 RequestManager對象
private static final RequestManagerFactory DEFAULT\_FACTORY = new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
//實例化一個RequestManager
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
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;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
//添加生命週期監聽
if (Util.isOnBackgroundThread()) {
//子線程通過handler將當前對象註冊到ActivityFragmentLifecycle
mainHandler.post(addSelfToLifecycle);
} else {
//將當前對象註冊到ActivityFragmentLifecycle
lifecycle.addListener(this);
}
//添加網絡變化的監聽
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
//...
//RequestManager實現了fragment生命週期回調
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
}
構建 RequestManager 的時候將 RequestManager 的生命週期與 Fragment 關聯起來了。
Fragment 是依附在 Activity,所以 Activity 的生命週期在 Fragment 中都有,接着我們來看下 RequestManagerFragment:
public class RequestManagerFragment extends Fragment {
//生命週期的關鍵就在ActivityFragmentLifecycle
private final ActivityFragmentLifecycle lifecycle;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
RequestManagerFragment(@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();
unregisterFragmentWithRoot();
}
//...
}
生命週期的關鍵就在 lifecycle,Fragment 生命週期變化時會主動通知 lifecycle 執行相應方法。
接着看下 ActivityFragmentLifecycle:
class ActivityFragmentLifecycle implements Lifecycle {
//在Fragment生命週期變化時會通知所有的它的Listener
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@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();
}
}
}
這個 ActivityFragmentLifecycle 持有一個 lifecycleListeners,在 Fragment 生命週期變化時會通知所有的它的 Listener。
4.Glide 生命週期回調流程總結
image
Glide.with(this) 綁定了 Activity 的生命週期。在 Activity 內新建了一個無 UI 的 Fragment,這個 Fragment 持有一個 Lifecycle,通過 Lifecycle 在 Fragment 關鍵生命週期通知 RequestManager 進行相關從操作。在生命週期 onStart 時繼續加載,onStop 時暫停加載,onDestory 時停止加載任務和清除操作。
Glide 爲什麼對 Fragment 做緩存?
//添加到Map緩存中(防止fragment重複創建)
pendingRequestManagerFragments.put(fm, current);
//將fragment綁定到activity
fm.beginTransaction().add(current, FRAGMENT\_TAG).commitAllowingStateLoss();
//添加後發送清理緩存的消息
handler.obtainMessage(ID\_REMOVE\_FRAGMENT\_MANAGER, fm).sendToTarget();
一個場景:通過 Glide 加載兩張圖片並設置到兩個 ImageView 上。
Glide.with(this).load(imageUrl1).into(imageView1);//msg1
Glide.with(this).load(imageUrl2).into(imageView2);//msg2
image
執行到 getRequestManagerFragment 這個方法時,會通過開啓事務的方式綁定 fragment 到 activity,綁定操作最終是通過主線程的 handler 發送消息處理的,Handler 中的消息時按照順序執行的。如果不把 msg1 構建的 RequestManagerFragment 放到 pendingRequestManagerFragments 中,那麼在執行 msg2 的時候會重新創建一個重複的 fragment 並 add。最後發消息清理緩存(避免內存泄漏和減少內存壓力),因爲消息是按照順序執行的,執行清理緩存的時候 msg1 和 msg2 已經執行完畢。
Glide 如何監聽網絡變化?
在構建 RequestManager 的時候通過lifecycle.addListener(connectivityMonitor);
添加網絡變化的監聽 ,Fragment 生命週期的變化會通知到默認實現類 DefaultConnectivityMonitor 中對應的方法。在 onStart 中 registerReceiver(註冊監聽手機網絡變化的廣播), 在 onStop 中 unregisterReceiver。有網絡重連後重啓請求。
final class DefaultConnectivityMonitor implements ConnectivityMonitor {
private static final String TAG = "ConnectivityMonitor";
private final Context context;
@SuppressWarnings("WeakerAccess") @Synthetic final ConnectivityListener listener;
@SuppressWarnings("WeakerAccess") @Synthetic boolean isConnected;
private boolean isRegistered;
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
@Override
public void onReceive(@NonNull Context context, Intent intent) {
boolean wasConnected = isConnected;
//判斷網絡狀態
isConnected = isConnected(context);
if (wasConnected != isConnected) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "connectivity changed, isConnected: " + isConnected);
}
listener.onConnectivityChanged(isConnected);
}
}
};
DefaultConnectivityMonitor(@NonNull Context context, @NonNull ConnectivityListener listener) {
this.context = context.getApplicationContext();
this.listener = listener;
}
private void register() {
if (isRegistered) {
return;
}
// Initialize isConnected.
isConnected = isConnected(context);
try {
// See #1405
context.registerReceiver(connectivityReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY\_ACTION));
isRegistered = true;
} catch (SecurityException e) {
// See #1417, registering the receiver can throw SecurityException.
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to register", e);
}
}
}
private void unregister() {
if (!isRegistered) {
return;
}
context.unregisterReceiver(connectivityReceiver);
isRegistered = false;
}
@SuppressWarnings("WeakerAccess")
@Synthetic
// Permissions are checked in the factory instead.
@SuppressLint("MissingPermission")
boolean isConnected(@NonNull Context context) {
ConnectivityManager connectivityManager =
Preconditions.checkNotNull(
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY\_SERVICE));
NetworkInfo networkInfo;
try {
networkInfo = connectivityManager.getActiveNetworkInfo();
} catch (RuntimeException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to determine connectivity status when connectivity changed", e);
}
// Default to true;
return true;
}
return networkInfo != null && networkInfo.isConnected();
}
@Override
public void onStart() {
register();
}
@Override
public void onStop() {
unregister();
}
@Override
public void onDestroy() {
// Do nothing.
}
}
回調 ConnectivityListener 的 onConnectivityChanged 來處理請求
private class RequestManagerConnectivityListener
implements ConnectivityMonitor.ConnectivityListener {
@GuardedBy("RequestManager.this")
private final RequestTracker requestTracker;
RequestManagerConnectivityListener(@NonNull RequestTracker requestTracker) {
this.requestTracker = requestTracker;
}
@Override
public void onConnectivityChanged(boolean isConnected) {
if (isConnected) {
synchronized (RequestManager.this) {
//網絡重連後重啓請求
requestTracker.restartRequests();
}
}
}
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。