Android源碼進階之Glide生命周期管理機制詳解
本文轉(zhuǎn)載自微信公眾號「Android開發(fā)編程」,作者Android開發(fā)編程。轉(zhuǎn)載本文請聯(lián)系A(chǔ)ndroid開發(fā)編程公眾號。
前言
glide緩存策略我們分析過了;
glide加載流程我們上一篇文章也分析過了;
那么這次我們再來分析下Glide生命周期管理詳解
一、Glide生命周期原理詳解
- Glide.with(this)
- // .asBitmap()//只允許加載靜態(tài)圖片,若傳入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)//設(shè)置加載尺寸
- .skipMemoryCache(true)//禁用內(nèi)存緩存功能
- .diskCacheStrategy(DiskCacheStrategy.NONE)//不緩存任何內(nèi)容
- // .diskCacheStrategy(DiskCacheStrategy.DATA)//只緩存原始圖片
- // .diskCacheStrategy(DiskCacheStrategy.RESOURCE)//只緩存轉(zhuǎn)換后的圖片
- // .diskCacheStrategy(DiskCacheStrategy.ALL)//緩存所有
- // .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)//Glide根據(jù)圖片資源智能地選擇使用哪一種緩存策略(默認)
- .listener(new RequestListener<Drawable>() {//監(jiān)聽圖片加載狀態(tài)
- //圖片加載完成
- @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);//圖片最終要展示的地方
1、Glide.with(this)
with方法可以接受Context,Activity,F(xiàn)ragmentActivity,F(xiàn)ragment和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,通過建造者模式創(chuàng)建了一個GlideBuilder對象(資源請求線程池,本地緩存加載線程池,動畫線程池,內(nèi)存緩存器,磁盤緩存工具等等);
構(gòu)造完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)
- //拿到當(dāng)前Activity的FragmentManager
- android.app.FragmentManager fm = activity.getFragmentManager();
- //生成一個Fragment去綁定一個請求管理RequestManager
- return fragmentGet(
- activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
- }
- }
如果當(dāng)前線程是子線程,則不需要對Glide生命周期進行管理,否則通過fragmentGet函數(shù)創(chuàng)建一個fragment:
- private RequestManager fragmentGet(@NonNull Context context,
- @NonNull android.app.FragmentManager fm,
- @Nullable android.app.Fragment parentHint,
- boolean isParentVisible) {
- //①在當(dāng)前Activity添加一個Fragment用于管理請求的生命周期
- RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
- //獲取RequestManager
- RequestManager requestManager = current.getRequestManager();
- //如果不存在RequestManager,則創(chuàng)建
- if (requestManager == null) {
- Glide glide = Glide.get(context);
- //②構(gòu)建RequestManager
- //current.getGlideLifecycle()就是ActivityFragmentLifecycle,也就是構(gòu)建RequestManager時會傳入fragment中的ActivityFragmentLifecycle
- requestManager =
- factory.build(
- glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
- //將構(gòu)建出來的RequestManager綁定到fragment中
- current.setRequestManager(requestManager);
- }
- //返回當(dāng)前請求的管理者
- return requestManager;
- }
2、Fragment與Activity的綁定—>getRequestManagerFragment:
- private RequestManagerFragment getRequestManagerFragment(
- @NonNull final android.app.FragmentManager fm,
- @Nullable android.app.Fragment parentHint,
- boolean isParentVisible) {
- //通過TAG拿到已經(jīng)實例化過的fragment(也就是同一個Activity Glide.with多次,沒必要創(chuàng)建多個fragment)
- RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
- if (current == null) {
- //如果當(dāng)前Activity中沒有拿到管理生命周期的fragment,那就從緩存取
- current = pendingRequestManagerFragments.get(fm);
- if (current == null) {
- //如果緩存也沒有,直接new一個
- current = new RequestManagerFragment();
- current.setParentFragmentHint(parentHint);
- if (isParentVisible) {
- //執(zhí)行請求
- current.getGlideLifecycle().onStart();
- }
- //添加到Map緩存中(防止fragment重復(fù)創(chuàng)建)
- pendingRequestManagerFragments.put(fm, current);
- //將fragment綁定到activity
- fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
- //添加后發(fā)送清理緩存
- handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
- }
- }
- return current;
- }
3、構(gòu)建RequestManager并設(shè)置監(jiān)聽
- //此工廠就是為了構(gòu)建出 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));
- //添加生命周期監(jiān)聽
- if (Util.isOnBackgroundThread()) {
- //子線程通過handler將當(dāng)前對象注冊到ActivityFragmentLifecycle
- mainHandler.post(addSelfToLifecycle);
- } else {
- //將當(dāng)前對象注冊到ActivityFragmentLifecycle
- lifecycle.addListener(this);
- }
- //添加網(wǎng)絡(luò)變化的監(jiān)聽
- lifecycle.addListener(connectivityMonitor);
- defaultRequestListeners =
- new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
- setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
- glide.registerRequestManager(this);
- }
- //...
- //RequestManager實現(xiàn)了fragment生命周期回調(diào)
- @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);
- }
- }
構(gòu)建RequestManager的時候?qū)equestManager的生命周期與Fragment關(guān)聯(lián)起來了;
4、Fragment是依附在Activity,所以Activity的生命周期在Fragment中都有,接著我們來看下RequestManagerFragment:
- public class RequestManagerFragment extends Fragment {
- //生命周期的關(guān)鍵就在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();
- }
- //...
- }
生命周期的關(guān)鍵就在lifecycle,F(xiàn)ragment生命周期變化時會主動通知lifecycle執(zhí)行相應(yīng)方法;
接著看下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
Glide.with(this)綁定了Activity的生命周期。在Activity內(nèi)新建了一個無UI的Fragment,這個Fragment持有一個Lifecycle,通過Lifecycle在Fragment關(guān)鍵生命周期通知RequestManager進行相關(guān)從操作。在生命周期onStart時繼續(xù)加載,onStop時暫停加載,onDestory時停止加載任務(wù)和清除操作
二、Glide如何監(jiān)聽網(wǎng)絡(luò)變化
在構(gòu)建RequestManager的時候通過lifecycle.addListener(connectivityMonitor);添加網(wǎng)絡(luò)變化的監(jiān)聽 ,F(xiàn)ragment生命周期的變化會通知到默認實現(xiàn)類DefaultConnectivityMonitor中對應(yīng)的方法。在onStart中registerReceiver(注冊監(jiān)聽手機網(wǎng)絡(luò)變化的廣播), 在onStop中unregisterReceiver。有網(wǎng)絡(luò)重連后重啟請求。
- 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;
- //判斷網(wǎng)絡(luò)狀態(tài)
- 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.
- }
- }
回調(diào)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) {
- //網(wǎng)絡(luò)重連后重啟請求
- requestTracker.restartRequests();
- }
- }
- }
- }
總結(jié)
1、Glide使用特點:
- 使用簡單
- 可配置度高,自適應(yīng)程度高
- 支持常見圖片格式(jpg、png、gif、webp)
- 支持多種數(shù)據(jù)源(網(wǎng)絡(luò)、本地、資源、Assets等)
- 高效緩存策略(支持Memory和Disk圖片緩存,默認Bitmap格式采用RGB_565內(nèi)存小)
- 生命周期集成(根據(jù)Activity/Fragment生命周期自動管理請求)
- 高效處理Bitmap(使用BitmapPool復(fù)用Bitmap,主動調(diào)用recycle回收需要回收的Bitmap)
2、關(guān)于glide的知識點還是有很多的,我們還會繼續(xù)總結(jié)分享給各位老鐵們