Glide 对生命周期的监听

作者: smart_dev | 来源:发表于2023-09-06 19:55 被阅读0次

    你一定听过Glide的优势之一是能够感知生命周期,从而暂停加载、回收资源等
    这里首先简述原理,通过构建一个空白的fragment,然后将这个fragment添加到Activity上,此时fragment便有了生命周期的感知能力。然后再想办法将这个感知信号传递到每个需要的地方即可。
    那接下来具体看下是如何实现的这些过程的。

    观察者模式

    Lifecycle

    可以理解成被观察者,抽象成具有生命周期的组件,接纳观察者

    public interface Lifecycle {
      void addListener(@NonNull LifecycleListener listener);
      void removeListener(@NonNull LifecycleListener listener);
    }
    

    LifecycleListener

    定义观察者能够感知到哪些生命周期信号

    public interface LifecycleListener {
      void onStart();
      void onStop();
      void onDestroy();
    }
    

    那现在其实还差个通知观察者的具体实现

    这里根据 Glide.with(context)传入的context类型不同,分为两种类型的生命周期。

    • ActivityFragmentLifecycle
    • ApplicationLifecycle

    ActivityFragmentLifecycle

    class ActivityFragmentLifecycle implements Lifecycle {
      // 注释1
      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);
        // 注释2
        if (isDestroyed) {
          listener.onDestroy();
        } else if (isStarted) {
          listener.onStart();
        } else {
          listener.onStop();
        }
      }
    
      @Override
      public void removeListener(@NonNull LifecycleListener listener) {
        lifecycleListeners.remove(listener);
      }
      
      // 注释3
      void onStart() {
        isStarted = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onStart();
        }
      }
      // 注释4
      void onStop() {
        isStarted = false;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onStop();
        }
      }
      // 注释5
      void onDestroy() {
        isDestroyed = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onDestroy();
        }
      }
    }
    
    • 注释1 用Set集合保存所有的观察者LifecycleListener
    • 注释2 这里是实现粘性事件特点,让后来的观察者及时收到当前最新的生命周期
    • 注释3、注释4、注释5 定义各个生命周期方法,从而循环通知观察者

    以上生命周期通知框架基本定义好了,那在哪里真的感知的然后通知的?

    RequestManagerFragment

    这里通过组合模式实现了生命周期的感知

    public class RequestManagerFragment extends Fragment {
      private static final String TAG = "RMFragment";
      private final ActivityFragmentLifecycle lifecycle;
      
      public RequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
      }
    
      @VisibleForTesting
      @SuppressLint("ValidFragment")
      RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
      }
    
      /**
       * Sets the current {@link com.bumptech.glide.RequestManager}.
       *
       * @param requestManager The request manager to use.
       */
      public void setRequestManager(@Nullable RequestManager requestManager) {
        this.requestManager = requestManager;
      }
    
      @NonNull
      ActivityFragmentLifecycle getGlideLifecycle() {
        return lifecycle;
      }
    
      /** Returns the current {@link com.bumptech.glide.RequestManager} or null if none exists. */
      @Nullable
      public RequestManager getRequestManager() {
        return requestManager;
      }
    
      @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();
      }
    
    }
    

    接着看下这个fragment是什么时候创建并添加到FragmentManager

    RequestManagerRetriever#getRequestManagerFragment
    @SuppressWarnings("deprecation")
    @VisibleForTesting
    // 注释1
    final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
        new HashMap<>();
    
    
    @SuppressWarnings("deprecation")
    @NonNull
    private RequestManagerFragment getRequestManagerFragment(
        @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
      // If we have a pending Fragment, we need to continue to use the pending Fragment. Otherwise
      // there's a race where an old Fragment could be added and retrieved here before our logic to
      // add our pending Fragment notices. That can then result in both the pending Fragmeng and the
      // old Fragment having requests running for them, which is impossible to safely unwind.
      // 注释2
      RequestManagerFragment current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        // 注释3
        current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = new RequestManagerFragment();
          current.setParentFragmentHint(parentHint);
          pendingRequestManagerFragments.put(fm, current);
          // 注释4
          fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
          // 注释5
          handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
        }
      }
      return current;
    }
    
    • 注释1 这里用 Map 来保存 fragment,达到复用
    • 注释2 如果map中已经有fragment,直接复用
    • 注释3 如果map中没有,尝试通过FragmentManager直接去查Fragment是否已经绑定,如果绑定就无需重复了。
    • 注释4 将新的fragment添加到页面上,从而达到感知到生命周期,这个添加的过程是异步的
    • 注释5 检查fragment是否添加成功或者添加失败,如果添加成功,就从Map中移除 (清理缓存)

    假如同时有多处调用该方法,所以在前面new 出来一个RequestManagerFragment,随后就把它放到pendingRequestManagerFragments中,那么task2再进来的时候从缓存中能取到,就不会再重新new和add了。
    那么下一个问题来了,为什么会出现下面这行代码,add后又需要马上发一个消息remove掉?在前面阻止掉task2重复new和add的操作后,就把这个缓存删掉,可以避免内存泄漏和内存压力
    因为这个时候已经添加完毕,下个任务到来的时候可以直接从fm中查找到。
    到这里,整个系统运转过程就差具体的观察者了,我们需要再看,以至于更好的理解Glide感知到生命周期后的策略。

    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);
      // 注释1
      RequestManager requestManager = current.getRequestManager();
      if (requestManager == null) {
        // TODO(b/27524013): Factor out this Glide.get() call.
        Glide glide = Glide.get(context);
        // 注释2
        requestManager =
            factory.build(
                glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
        // This is a bit of hack, we're going to start the RequestManager, but not the
        // corresponding Lifecycle. It's safe to start the RequestManager, but starting the
        // Lifecycle might trigger memory leaks. See b/154405040
        if (isParentVisible) {
          requestManager.onStart();
        }
        // 注释3
        current.setRequestManager(requestManager);
      }
      return requestManager;
    }
    
    • 这个方法返回 RequestManger,负责处理图片加载请求并管理加载过程中的生命周期和资源
    • 注释1 如果fragment中已经绑定了RequestManager,直接返回
    • 注释2 未绑定,就先创建一个RequestManager ,也就是在这个里面注册的观察者,后面看
    • 注释3 将这个RequestManager和 fragment 绑定

    RequestManagerFactory

     public interface RequestManagerFactory {
        @NonNull
        RequestManager build(
            @NonNull Glide glide,
            @NonNull Lifecycle lifecycle,
            @NonNull RequestManagerTreeNode requestManagerTreeNode,
            @NonNull Context context);
      }
    
      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) {
              // 注释1 
              return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
            }
          };
    }
    
    • 如果Glie 外面不做配置,默认使用的DEFAULT_FACTORY
    • 注释1 这里lifecyle就是我们在RequestManagerFragment中通过组合模式引入的 ActivityFragmentLifecycle

    RequestManager#构造方法

    这里我们关注 拿到这个Lifecycle 后 都注册了哪些观察者

    public class RequestManager implements LifecycleListener,... {
        ...
    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()) {
        Util.postOnUiThread(addSelfToLifecycle);
      } else {
        lifecycle.addListener(this);
      }
      lifecycle.addListener(connectivityMonitor);
    
      ...
    }
    
    private final Runnable addSelfToLifecycle =
        new Runnable() {
          @Override
          public void run() {
            lifecycle.addListener(RequestManager.this);
          }
        };
        
     ...   
    }
    

    总共有两处

    • 将当前RequestManager 注册成观察者,这样当收到生命周期感知后来暂停和恢复请求(本文不详细讨论),同时也会将信号转发到各个Target,下面会具体看如何转发的
    • 将网络监听器注册成观察者,通过监听生命周期来完成广播的注册和反注册

    RequestManager#生命周期方法

    @GuardedBy("this")
    private final TargetTracker targetTracker = new TargetTracker();
    
    @Override
    public synchronized void onStart() {
      resumeRequests();
      targetTracker.onStart();
    }
    
    @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() {
      targetTracker.onDestroy();
      for (Target<?> target : targetTracker.getAll()) {
        clear(target);
      }
      targetTracker.clear();
      requestTracker.clearRequests();  
      lifecycle.removeListener(this);
      lifecycle.removeListener(connectivityMonitor);
      Util.removeCallbacksOnUiThread(addSelfToLifecycle);
      glide.unregisterRequestManager(this);
    }
    
    • 管理 Request:在对应的生命周期中,开始请求、暂停请求、移除请求监听
    • 管理Target :收到生命周期回调后,又通过 TargetTracker 进行了转发,进而管理每个Target

    TargetTracker

    • 至于TargetTracker 什么时候关联的Target,这里不做讨论 track
    • 可以看到 每个Target 也实现了LifecycleListener ,这里又是一个新的观察者模式
    public final class TargetTracker implements LifecycleListener {
      private final Set<Target<?>> targets =
          Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());
    
      public void track(@NonNull Target<?> target) {
        targets.add(target);
      }
    
      public void untrack(@NonNull Target<?> target) {
        targets.remove(target);
      }
    
      @Override
      public void onStart() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onStart();
        }
      }
    
      @Override
      public void onStop() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onStop();
        }
      }
    
      @Override
      public void onDestroy() {
        for (Target<?> target : Util.getSnapshot(targets)) {
          target.onDestroy();
        }
      }
    
      @NonNull
      public List<Target<?>> getAll() {
        return Util.getSnapshot(targets);
      }
    
      public void clear() {
        targets.clear();
      }
    }
    

    相关文章

      网友评论

        本文标题:Glide 对生命周期的监听

        本文链接:https://www.haomeiwen.com/subject/otrcvdtx.html