Glide 生命週期管理

作者:靈魂攻城獅
鏈接:https://www.jianshu.com/p/190285e18ae1

Glide 生命週期管理

1.Glide 特點
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 轉碼,版權歸原作者所有。