Glide源码阅读-生命周期管理

Glide生命周期管理:
1、Glide如何绑定Activity、Fragment生命周期
2、Glide如何监听内存变化,网络变化
3、Glide如何处理请求的生命周期

本文基于Glide4.9.0,依赖Glide方式如下:

    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'

生命周期绑定:

Glide生命周期绑定是从入口单例类Glide开始的,通过with()多个重载方法来实现生命周期的绑定工作:

public static RequestManager with(@NonNull Activity activity)
public static RequestManager with(@NonNull FragmentActivity activity)
public static RequestManager with(@NonNull Fragment fragment)
public static RequestManager with(@NonNull android.app.Fragment fragment)//已过期
public static RequestManager with(@NonNull View view)

//1、以Activity为例
public static RequestManager with(@NonNull Activity activity) {
  return getRetriever(activity).get(activity);
}

//2、Glide get方法初始化完后得到一个RequestManagerRetriever对象
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
  // Context could be null for other reasons (ie the user passes in null), but in practice it will
  // only occur due to errors with the Fragment lifecycle.
  Preconditions.checkNotNull(
      context,
      "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
          + "returns null (which usually occurs when getActivity() is called before the Fragment "
          + "is attached or after the Fragment is destroyed).");
  return Glide.get(context).getRequestManagerRetriever();
}

//3、看下RequestManagerRetriever的get方法
public RequestManager get(@NonNull Activity activity) {
  if (Util.isOnBackgroundThread()) {
    return get(activity.getApplicationContext());
  } else {
    assertNotDestroyed(activity);
    android.app.FragmentManager fm = activity.getFragmentManager();
    return fragmentGet(
        activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}

//同上面3一样,也是RequestManagerRetriever的get方法重载
//不同点1:是上面传入的是FragmentManager,这里传的是ChildFragmentManage
//不同点2:当Context是Activity时,parentHint为null,当Context为Fragment时,parentHint为fragment
public RequestManager get(@NonNull Fragment fragment) {
  Preconditions.checkNotNull(fragment.getActivity(),
        "You cannot start a load on a fragment before it is attached or after it is destroyed");
  if (Util.isOnBackgroundThread()) {
    return get(fragment.getActivity().getApplicationContext());
  } else {
    FragmentManager fm = fragment.getChildFragmentManager();
    return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
  }

如果是在子线程进行的with操作,那么Glide默认使用ApplicationContext,可以理解为不对请求的生命周期进行管理,通过Context拿到FragmentManager,下面开始构建RequestManagerFragment和RequestManager:

//1、根据FragmentManager、parentHint、isParentVisible构建RequestManagerFragment 
private RequestManager fragmentGet(@NonNull Context context,
    @NonNull android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  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.get(context);
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    current.setRequestManager(requestManager);
  }
  return requestManager;
}

//2、开始构建RequestManagerFragment 
private RequestManagerFragment getRequestManagerFragment(
    @NonNull final android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
 //根据FRAGMENT_TAG在FragmentManager中查找是否已经存在RequestManagerFragment实例
  RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
      //在pendingRequestManagerFragments中查找是否存在RequestManagerFragment实例
    current = pendingRequestManagerFragments.get(fm);
    if (current == null) {//没查找到,直接new一个实例
      current = new RequestManagerFragment();
      current.setParentFragmentHint(parentHint);//设置parentHint
      if (isParentVisible) {//界面可见,回调任务开始
        current.getGlideLifecycle().onStart();
      }
      pendingRequestManagerFragments.put(fm, current);//一个以FragmentManager为key,RequestManagerFragment为value的HashMap
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();//通过事物add到FragmentManager
      handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();//通过Handler发送ID_REMOVE_FRAGMENT_MANAGER
    }
  }
  return current;
}

//handler接收到ID_REMOVE_FRAGMENT_MANAGER做了什么操作
public boolean handleMessage(Message message) {
  boolean handled = true;
  Object removed = null;
  Object key = null;
  switch (message.what) {
    case ID_REMOVE_FRAGMENT_MANAGER: //根据fm,从pendingRequestManagerFragments中删除对应的key-value
      android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
      key = fm;
      removed = pendingRequestManagerFragments.remove(fm);
      break;
    case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
      FragmentManager supportFm = (FragmentManager) message.obj;
      key = supportFm;
      removed = pendingSupportRequestManagerFragments.remove(supportFm);
      break;
    default:
      handled = false;
      break;
  }
  if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
    Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
  }
  return handled;
}

疑问:为什么需要一个pendingRequestManagerFragments?为什么在fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();操作之前要先把current添加到pendingRequestManagerFragments里面,然后通过handler发送ID_REMOVE_FRAGMENT_MANAGER移除,而不能直接移除呢?
这其实跟Android的主线程Loop机制和Fragment的事物机制有关,FragmentManager的commitAllowingStateLoss()操作是异步,也是通过Handler的Loop机制从loop中取消息然后进行绑定处理,我们知道Loop里面的消息是按时间顺序来处理的,ID_REMOVE_FRAGMENT_MANAGER消息在FragmentManager的commitAllowingStateLoss()之后,这就避免了RequestManagerFragment 的重复实例化问题,假设连续调用Glide.with的时候第一次Glide.with已经对RequestManagerFragment 进行了实例化操作,并执行了FragmentManager的commitAllowingStateLoss(),第二次的Glide.with操作执行到fm.findFragmentByTag(FRAGMENT_TAG)有可能得到null但是前一次实例化已经完成,并添加到了pendingRequestManagerFragments里面,只要从pendingRequestManagerFragments获取到的RequestManagerFragment 不为null,我们就不需要进行重复的实例化了。

接下来我们继续看RequestManagerFragment实例化时做了什么

//RequestManagerFragment构造方法
public RequestManagerFragment() {
  this(new ActivityFragmentLifecycle());
}

@SuppressLint("ValidFragment")
RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
  this.lifecycle = lifecycle;
}
//RequestManagerFragment生命周期相关代码
@Override
public void onStart() {//RequestManagerFragment onStart()
  super.onStart();
  lifecycle.onStart();
}

@Override
public void onStop() {//RequestManagerFragment onStop()
  super.onStop();
  lifecycle.onStop();
}

@Override
public void onDestroy() {//RequestManagerFragment onDestroy()
  super.onDestroy();
  lifecycle.onDestroy();
  unregisterFragmentWithRoot();
}

//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);
  }

  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();
    }
  }
}

//LifecycleListener代码
public interface LifecycleListener {

  /**
   * Callback for when {@link android.app.Fragment#onStart()}} or {@link
   * android.app.Activity#onStart()} is called.
   */
  void onStart();

  /**
   * Callback for when {@link android.app.Fragment#onStop()}} or {@link
   * android.app.Activity#onStop()}} is called.
   */
  void onStop();

  /**
   * Callback for when {@link android.app.Fragment#onDestroy()}} or {@link
   * android.app.Activity#onDestroy()} is called.
   */
  void onDestroy();
}

直接new了一个ActivityFragmentLifecycle,这个类实际是一个生命周期回调的管理类,实现了Lifecycle接口,所有的LifecycleListener会添加到一个集合中,当RequestManagerFragment的生命周期发生变化时,会调用对应的ActivityFragmentLifecycle方法,这个方法会遍历所有的LifecycleListener通知执行对应的生命周期操作。

RequestManager的实例化:

//1、RequestManagerRetriever的fragmentGet方法
private RequestManager fragmentGet(@NonNull Context context,
    @NonNull android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
  RequestManager requestManager = current.getRequestManager();
  if (requestManager == null) {//requestManager为null时,通过factory.build进行构建
    // TODO(b/27524013): Factor out this Glide.get() call.
    Glide glide = Glide.get(context);
    requestManager =
        factory.build(
            glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    current.setRequestManager(requestManager);
  }
  return requestManager;
}

//RequestManager代码精简,只显示跟LifecycleListener相关的
public class RequestManager implements LifecycleListener, ...{
    
    private final Runnable addSelfToLifecycle = new Runnable() {
      @Override
      public void run() {
        lifecycle.addListener(RequestManager.this);
      }
    };
    
  RequestManager(...,Lifecycle lifecycle,...) {
    ...
    this.lifecycle = lifecycle;
    ...
    // If we're the application level request manager, we may be created on a background thread.
    // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
    // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
    // This should be entirely safe.
    if (Util.isOnBackgroundThread()) {//当前线程为子线程时,通过handler注册到主线程
      mainHandler.post(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);//网络监听器,实现了LifecycleListener


    ...
  }

@Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  /**
   * Lifecycle callback that unregisters for connectivity events (if the
   * android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
   */
  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }

  /**
   * Lifecycle callback that cancels all in progress requests and clears and recycles resources for
   * all completed requests.
   */
  @Override
  public synchronized void onDestroy() {
    ...
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    ..
  }
}

RequestManager实现了LifecycleLisenter接口,并在构造器中,给lifecycle添加listener,而这里的lifecycle正好对应了RequestManagerFragment中的lifecycle。就这样RequestManager可以感知RequestManagerFragment的生命周期了。至此就可以知道Glide图片加载可以智能感知Activity、Fragment的生命周期函数进行请求的重启、暂停、清除等操作

监听网络变化

//RequestManager构造方法
public RequestManager(
    @NonNull Glide glide, @NonNull Lifecycle lifecycle,
    @NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
  this(
      glide,
      lifecycle,
      treeNode,
      new RequestTracker(),
      glide.getConnectivityMonitorFactory(),
      context);
}
//构造方法
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 we're the application level request manager, we may be created on a background thread.
  // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
  // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
  // This should be entirely safe.
  if (Util.isOnBackgroundThread()) {
    mainHandler.post(addSelfToLifecycle);
  } else {
    lifecycle.addListener(this);
  }
  lifecycle.addListener(connectivityMonitor);

  defaultRequestListeners =
      new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
  setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

  glide.registerRequestManager(this);
}

RequestManager初始化时,通过ConnectivityMonitorFactory 工厂类构建connectivityMonitor ,ConnectivityMonitorFactory 唯一实现类如下:

//ConnectivityMonitorFactory
public interface ConnectivityMonitorFactory {

  @NonNull
  ConnectivityMonitor build(
      @NonNull Context context,
      @NonNull ConnectivityMonitor.ConnectivityListener listener);
}
//DefaultConnectivityMonitorFactory 
public class DefaultConnectivityMonitorFactory implements ConnectivityMonitorFactory {
  private static final String TAG = "ConnectivityMonitor";
  private static final String NETWORK_PERMISSION = "android.permission.ACCESS_NETWORK_STATE";

  @NonNull
  @Override
  public ConnectivityMonitor build(
      @NonNull Context context,
      @NonNull ConnectivityMonitor.ConnectivityListener listener) {
    int permissionResult = ContextCompat.checkSelfPermission(context, NETWORK_PERMISSION);
    boolean hasPermission = permissionResult == PackageManager.PERMISSION_GRANTED;
    if (Log.isLoggable(TAG, Log.DEBUG)) {
      Log.d(
          TAG,
          hasPermission
              ? "ACCESS_NETWORK_STATE permission granted, registering connectivity monitor"
              : "ACCESS_NETWORK_STATE permission missing, cannot register connectivity monitor");
    }
    return hasPermission
        ? new DefaultConnectivityMonitor(context, listener) : new NullConnectivityMonitor();
  }

判断是否有监听网络变化的权限,有权限则new DefaultConnectivityMonitor()

//DefaultConnectivityMonitor
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) {
      // #1405 shows that this throws a SecurityException.
      // b/70869360 shows that this throws NullPointerException on APIs 22, 23, and 24.
      // b/70869360 also shows that this throws RuntimeException on API 24 and 25.
      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.
  }
}

//RequestManagerConnectivityListener
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();
      }
    }
  }
}

DefaultConnectivityMonitor 实现了ConnectivityMonitor,RequestManagerConnectivityListener实现了ConnectivityMonitor.ConnectivityListener,并在RequestManager初始化时,添加到了lifecycle中,到这里,Glide监测网络状态来重启请求的实现方式就呼之欲出了,大体步骤如下:
在组件对应的生命周期中,会调用lifecycle的生命周期回调,DefaultConnectivityMonitor在onStart方法回调时添加了监听网络状态变化的广播,在onStop取消了广播监听,所以可以在网络连接状态变化时进行请求重启。

监听内存变化

//Glide实现了ComponentCallbacks2
public class Glide implements ComponentCallbacks2{
 /**
 * Clears some memory with the exact amount depending on the given level.
 *
 * @see android.content.ComponentCallbacks2#onTrimMemory(int)
 */
    public void trimMemory(int level) {
  // Engine asserts this anyway when removing resources, fail faster and consistently
      Util.assertMainThread();
  // memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
      memoryCache.trimMemory(level);
      bitmapPool.trimMemory(level);
      arrayPool.trimMemory(level);
    }
    
    @Override
    public void onLowMemory() {
      clearMemory();
    }
    
    /**
     * Clears as much memory as possible.
     *
     * @see android.content.ComponentCallbacks#onLowMemory()
     * @see android.content.ComponentCallbacks2#onLowMemory()
     */
    public void clearMemory() {
      // Engine asserts this anyway when removing resources, fail faster and consistently
      Util.assertMainThread();
      // memory cache needs to be cleared before bitmap pool to clear re-pooled Bitmaps too. See #687.
      memoryCache.clearMemory();
      bitmapPool.clearMemory();
      arrayPool.clearMemory();
    }
}

//ComponentCallbacks2,继承了ComponentCallbacks
public interface ComponentCallbacks2 extends ComponentCallbacks {
    int TRIM_MEMORY_BACKGROUND = 40;
    int TRIM_MEMORY_COMPLETE = 80;
    int TRIM_MEMORY_MODERATE = 60;
    int TRIM_MEMORY_RUNNING_CRITICAL = 15;
    int TRIM_MEMORY_RUNNING_LOW = 10;
    int TRIM_MEMORY_RUNNING_MODERATE = 5;
    int TRIM_MEMORY_UI_HIDDEN = 20;

    void onTrimMemory(int var1);
}

//ComponentCallbacks 
public interface ComponentCallbacks {
    void onConfigurationChanged(Configuration var1);

    void onLowMemory();
}

//RequestManager构造方法
RequestManager(Glide glide,...) {
        this.glide = glide;
        ...
}

RequestManager持有Glide的引用,Glide实现了ComponentCallbacks2接口,可以监听内存不足时的回调,实现了对内部内存缓存的自动回收

如何处理请求的生命周期

综上,根据Glide.with()里面的参数,Glide的请求是和传进去的Context共存亡的,如Context是Activity或者Fragment,Glide会添加一个RequestManagerFragment用于感应组件的生命周期回调,并在回调的生命周期里面统一对请求进行管理,如context类型是ApplicationContext或在子线程里调用的请求,Glide不对请求的生命周期进行管理(即应用已退入了后台,界面已被回收,只要进程没死,Glide也不会停止该请求)

有趣的知识点:

RequestManagerFragment里的成员变量rootRequestManagerFragment
Glide每当创建一个RequestManagerFragment时都会尝试实例化rootRequestManagerFragment,这个fragment是顶级的Activity所创建的RequestManagerFragment。
相关代码:

//RequestManagerFragment相关代码

private final Set<RequestManagerFragment> childRequestManagerFragments = new HashSet<>();

@SuppressWarnings("deprecation")
private void registerFragmentWithRoot(@NonNull Activity activity) {
  unregisterFragmentWithRoot();
  rootRequestManagerFragment =
      Glide.get(activity).getRequestManagerRetriever().getRequestManagerFragment(activity);
  if (!equals(rootRequestManagerFragment)) {//Notice1
    rootRequestManagerFragment.addChildRequestManagerFragment(this);
  }
}

private void unregisterFragmentWithRoot() {
  if (rootRequestManagerFragment != null) {
    rootRequestManagerFragment.removeChildRequestManagerFragment(this);
    rootRequestManagerFragment = null;
  }
}

@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
  super.onAttach(activity);
  try {
    registerFragmentWithRoot(activity);
  } catch (IllegalStateException e) {
    // OnAttach can be called after the activity is destroyed, see #497.
    if (Log.isLoggable(TAG, Log.WARN)) {
      Log.w(TAG, "Unable to register fragment with root", e);
    }
  }
}

可以看到,不管当前的RequestManagerFragment是通过何种方式创建的,都会在onAttach时,拿到当前所绑定的Activity的FragmentManager来实例化一个RequestManagerFragment,这个RequestManagerFragment可能是自身(即已经通过Glide.with(activity)这种方式实例化过了),而如果是通过with(Fragment fragment)这种方式创建的RequestManagerFragment,rootRequestManagerFragment将指向当前fragment所绑定Activity的RequestManagerFragment,如果当前Activity没绑定过RequestManagerFragment,那么会通过FragmentManager开启事物绑定一个RequestManagerFragment,当发现自己不是rootRequestManagerFragment时,那么会将自己保存到rootRequestManagerFragment中的一个集合里面(如上面代码标识的Notice1)。

简而言之:Glide会为Activity创建一个RequestManagerFragment作为rootFragment,并保存了该Activity底下所有Fragment所创建的RequestManagerFragment(如果有的话)

RequestManagerFragment里的成员变量requestManagerTreeNode
RequestManagerFragment初始化时,同时也会初始化一个RequestManagerTreeNode,顾名思义,这个类是用来保存请求树节点的。
比如一个Activity采用ViewPager+Fragment的形式,而Fragment里面又是一个ViewPager+Fragment的形式,这个时候,假设其中一个RequestManagerFragment生命周期方法走了,怎么知道哪些RequestManagerFragment绑定的LifeCycle应该得到调用呢?理想的情况是,应该让绑定该RequestManagerFragment的Fragment名下所有的Fragment绑定的RequestManagerFragment的生命周期得到回调。
如下面这种情景,Activity中有两个Fragment,两个Fragment里又各自有两个Fragment,所有的Fragment中,均通过with(this)的方式来加载图片,经过之前的分析我们可以知道,rootRequestManagerFragment的集合中会保存有子Fragment对应的RequestManagerFragment。如下示意图:


RMF例子.png

当Fragment1生命周期改变时(对应的Fragment1的RMF也会变化),我们希望Fragment1-1和Fragment1-2所绑定的RMF也要立即做出反应(Fragment2及其底下的RequestManagerFragment则不响应生命周期事件),我们知道任何一个RequestManagerFragment都可以通过rootRequestFragment拿到这六个RMF,继而拿到其所对应的RequestManager,问题是怎么确定是我们要的Fragment1-1和Fragment1-2所对应的RMF?这就是RequestManagerTreeNode干的事情,RequestManagerFragment中的内部类实现了RequestManagerTreeNode:

//RequestManagerTreeNode 
public interface RequestManagerTreeNode {
  /**
   * Returns all descendant {@link RequestManager}s relative to the context of the current
   * {@link RequestManager}.
   */
  @NonNull
  Set<RequestManager> getDescendants();
}

//FragmentRequestManagerTreeNode,重点看下getDescendantRequestManagerFragments()
private class FragmentRequestManagerTreeNode implements RequestManagerTreeNode {

  @Synthetic
  FragmentRequestManagerTreeNode() { }

  @SuppressWarnings("deprecation")
  @NonNull
  @Override
  public Set<RequestManager> getDescendants() {
    Set<RequestManagerFragment> descendantFragments = getDescendantRequestManagerFragments();
    Set<RequestManager> descendants = new HashSet<>(descendantFragments.size());
    for (RequestManagerFragment fragment : descendantFragments) {
      if (fragment.getRequestManager() != null) {
        descendants.add(fragment.getRequestManager());
      }
    }
    return descendants;
  }

  @SuppressWarnings("deprecation")
  @Override
  public String toString() {
    return super.toString() + "{fragment=" + RequestManagerFragment.this + "}";
  }
}

//RequestManagerFragment的getDescendantRequestManagerFragments()方法
Set<RequestManagerFragment> getDescendantRequestManagerFragments() {
  if (equals(rootRequestManagerFragment)) {
    return Collections.unmodifiableSet(childRequestManagerFragments);
  } else if (rootRequestManagerFragment == null
      || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
    // Pre JB MR1 doesn't allow us to get the parent fragment so we can't introspect hierarchy,
    // so just return an empty set.
    return Collections.emptySet();
  } else {
    Set<RequestManagerFragment> descendants = new HashSet<>();
    for (RequestManagerFragment fragment : rootRequestManagerFragment
        .getDescendantRequestManagerFragments()) {
      if (isDescendant(fragment.getParentFragment())) {
        descendants.add(fragment);
      }
    }
    return Collections.unmodifiableSet(descendants);
  }
}

//RequestManagerFragment的isDescendant方法
private boolean isDescendant(@NonNull Fragment fragment) {
  Fragment root = getParentFragment();
  Fragment parentFragment;
  while ((parentFragment = fragment.getParentFragment()) != null) {
    if (parentFragment.equals(root)) {
      return true;
    }
    fragment = fragment.getParentFragment();
  }
  return false;
}

以上代码,我们发现FragmentRequestManagerTreeNode的作用就是通过getDescendantRequestManagerFragments筛选出符合条件的RequestManagerFragment并将其RequestManager加入集合中返回,我们当前生命周期发生变化的是Fragment1,getDescendantRequestManagerFragments执行顺序(HashSet是无序的,这只是一个假设)如下:
Fragment1的RMF调用getParentFragment()得到Fragment1
当遍历到Fragment1-1 RMF时,参数传递过来的是Fragment1-1,root 则为Fragment1,isDescendant条件符合
当遍历到Fragment1-2 RMF时,参数传递过来的是Fragment1-2,root 则为Fragment1,isDescendant条件符合
当遍历到Fragment2-1RMF时,参数传递过来的是Fragment2-1,root 则为Fragment2不符合

综上:RequestManagerTreeNode可以先通过绑定的RequestManagerFragment的getDescendantRequestManagerFragments()方法获取到所有的后裔(Descendant)RequestManagerFragments(即底下所有子Fragment绑定的RequestManagerFragment),并通过getDescendants()方法获取到后裔RequestManagerFragment所对应的RequestManager

有趣的地方在于,虽然在构造RequestManager时传进去了RequestManagerTreeNode,但是在整个Glide流程里,Glide并没有通过RequestManagerTreeNode在组件生命周期回调时对RequestManager进行相关回调操作,事实上,当前RequestManagerFragment生命周期被调用时,就意味着后裔RequestManagerFragment生命周期也会被调用,后裔RequestManagerFragment的RequestManager会根据注册的LifeCycle对请求进行对应的暂停、恢复处理。

Glide暴露了对整个后裔操作的相关接口给开发者调用:

//在RequestManager中
public synchronized void pauseRequestsRecursive() {
  pauseRequests();
  for (RequestManager requestManager : treeNode.getDescendants()) {
    requestManager.pauseRequests();
  }
}

public synchronized void resumeRequestsRecursive() {
  Util.assertMainThread();
  resumeRequests();
  for (RequestManager requestManager : treeNode.getDescendants()) {
    requestManager.resumeRequests();
  }
}

参考链接

第一次发文章,有错误请回复,谢谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容