1. 程式人生 > >Glide之生命週期管理

Glide之生命週期管理

 關於Glide的生命週期設計是Glide的一個很大亮點,現在就來看一下Glide生命週期的實現。
 在Glide原始碼解析這篇文章中就說過在Glide.with(context)中就實現了生命週期管理,with根據傳入的引數有不同的實現。

  //傳入一個Context
  public static RequestManager with(@NonNull Context context)
  //傳入一個activity
  public static RequestManager with(@NonNull Activity activity)
  //傳入一個FragmentActivity 
public static RequestManager with(@NonNull FragmentActivity activity) //傳入一個Fragment public static RequestManager with(@NonNull Fragment fragment) //傳入一個View public static RequestManager with(@NonNull View view)

 雖然有這麼多型別,但其實可以分為兩類的。

  • 傳入一個ApplicationContext,Glide的生命週期就相當於綁定了整個應用,只要應用不退出,任何時候都能夠載入,也可以理解為不對Glide生命週期進行管理。
  • 傳入activity、FragmentActivity 、Fragment 及View ,這樣就會建立一個看不見的fragment,Glide的生命週期就隨著該Fragment的變化而變化。

 當傳入引數為ApplicationContext時,程式碼實現如下。

  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
  //由於傳入引數是ApplicationContext,所以最終呼叫getApplicationManager方法。
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) { //判斷context型別是不是FragmentActivity return get((FragmentActivity) context); } else if (context instanceof Activity) { //判斷context型別是不是Activity return get((Activity) context); } else if (context instanceof ContextWrapper) { //判斷context型別是不是ContextWrapper return get(((ContextWrapper) context).getBaseContext()); } } //context型別屬於ApplicationContext return getApplicationManager(context); }

 由於傳入引數是ApplicationContext,所以最終呼叫getApplicationManager方法。

  private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    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;
  }

 這裡就直接建立一個ApplicationLifecycle來管理生命週期,但ApplicationLifecycle並不受控制,所以就無法對Glide生命週期進行管理。
 以傳入引數型別為Activity為例,程式碼實現如下。

  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  public RequestManager get(@NonNull Activity activity) {
    //如果在子執行緒,則不對Glide生命週期就那些管理
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(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) {
    //建立一個fragment物件
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      //防止Glide物件被異常回收
      Glide glide = Glide.get(context);
      //建立一個RequestManager物件
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

 在該方法中,通過getRequestManagerFragment來獲得一個Fragment物件。然後拿到該Fragment對應的RequestManager 物件,如果該物件為null則建立一個RequestManager物件並將fragment中的ActivityFragmentLifecycle物件傳遞給RequestManager。先來看getRequestManagerFragment方法的實現。

  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //查詢tag為FRAGMENT_TAG的fragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      //從HashMap中取出fm
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        //建立fragment物件
        current = new RequestManagerFragment();
        //當fragment巢狀fragment時才會使用,否則parentHint是null
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          //開始執行請求
          current.getGlideLifecycle().onStart();
        }
        //將fm新增到HashMap中,防止fragment的重複建立
        pendingRequestManagerFragments.put(fm, current);
        //新增fragment
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //從HashMap集合從移除fm
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

 從fm中去查詢tag為FRAGMENT_TAG的fragment是否存在,如果不存在就從pendingRequestManagerFragments這個HashMap中去取,如果沒有就建立一個fragment,新增到pendingRequestManagerFragments並且將該fragment繫結到activity,繫結成功後則從pendingRequestManagerFragments移除fragment。這裡的pendingRequestManagerFragments主要是防止fragment重複建立(Glide生命週期管理),因為每個activity必須對應一個唯一的fragment。來看一下這個fragment的實現RequestManagerFragment

public class RequestManagerFragment extends Fragment {
  private final ActivityFragmentLifecycle lifecycle;
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }
  public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
  ...
  @NonNull
  ActivityFragmentLifecycle getGlideLifecycle() {
    return 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();
  }
  ...
}

 再回到fragmentGet方法,fragment建立成功後,在建立RequestManager時會傳入fragment中的ActivityFragmentLifecycle,再來看RequestManager的實現。

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {
  private final Runnable addSelfToLifecycle = new Runnable() {
    @Override
    public void run() {
      lifecycle.addListener(RequestManager.this);
    }
  };
  public RequestManager(
      @NonNull Glide glide, @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),
        glide.getConnectivityMonitorFactory(),
        context);
  }

  // Our usage is safe here.
  @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
  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()) {
      //當在子執行緒時通過Handler將當前物件註冊到ActivityFragmentLifecycle
      mainHandler.post(addSelfToLifecycle);
    } else {
      //將當前物件註冊到ActivityFragmentLifecycle
      lifecycle.addListener(this);
    }
    //網路變化監聽
    lifecycle.addListener(connectivityMonitor);
    ...
  }
  //開始載入
  @Override
  public synchronized void onStart() {
    resumeRequests();
    //如果有動畫則開始動畫
    targetTracker.onStart();
  }
  //停止載入
  @Override
  public synchronized void onStop() {
    pauseRequests();
    //如果有動畫則動畫停止
    targetTracker.onStop();
  }
  //銷燬
  @Override
  public synchronized void onDestroy() {
    //如果有動畫則動畫結束並銷燬
    targetTracker.onDestroy();
    ...
  }
  //開始請求資料
  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
 ...
}

 可以看見在RequestManager的建構函式將RequestManager註冊到ActivityFragmentLifecycle中,再來看看ActivityFragmentLifecycle的實現。

class ActivityFragmentLifecycle implements Lifecycle {
  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);
  }
  //每個RequestManager對應一個LifecycleListener 
  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }
  //每個RequestManager對應一個LifecycleListener 
  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }
  //每個RequestManager對應一個LifecycleListener 
  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
}

 由於ActivityFragmentLifecycle物件是在fragment中建立並且它的onStart、onStop、onDestory方法與fragment一一對應,這樣就將RequestManager的生命週期就與fragment關聯起來了,也就與當前activity關聯起來。總體流程如下:
在這裡插入圖片描述

 當fragment生命週期發生變化時,通過ActivityFragmentLifecycle將變化告訴給RequestManagerDefaultConnectivityMonitor。而RequestManager又將此變化告訴給ImageViewTarget
 至於傳入引數為其他型別的實現基本上與activity的類似,就不在敘述。

【參考資料】
Glide生命週期管理
Glide原始碼分析(一) 圖片載入的生命週期