Glide 源码阅读笔记(二)

Glide 源码阅读笔记(二)

在第一篇文章中我简单介绍了 Glide 实例的创建过程,重点介绍了 Glide 的内存缓存实现和磁盘的缓存实现:Glide 源码阅读笔记(一)

本篇文章是系列文章中的第二篇,主要介绍一下 Glide 的生命周期管理,准备好了就开始吧。

源码阅读基于 Glide 4.16.0 版本

简单介绍 RequestManagerRetriever 和 RequestManager

我们使用 Glide 通常是通过 with() 方法来创建一个 RequestManager 来完成我们需要的请求,在前面的文章中我们已经介绍过了 Glide 实例的创建,而 RequestManager 的创建就要依赖于 RequestManagerRetriever,它是在 Glide 实例创建的时候就会创建。

先简单回忆下 Glide#with() 方法的实现:

Java 复制代码
  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    Preconditions.checkNotNull(context, DESTROYED_ACTIVITY_WARNING);
    return Glide.get(context).getRequestManagerRetriever();
  }
  
  @NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
  
  @NonNull
  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }
  
  @NonNull
  public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getContext()).get(fragment);
  }
  
  @NonNull
  public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }

通常我们传入 with() 方法中的参数可以是 ContextFragmentActivityFragmentViewRequestManagerRetriever 通过这些 Android 组件去查找对应的 RequestManager,如果没有对应的 RequestManager,会通过 RequestManagerFactory 创建一个,然后保存起来,下次再需要这个 RequestManager 就会复用这个实例(如果对应的 RequestManager 已经执行 onDestroy() 生命周期就无法复用)。 RequestManagerRetriever 还有一项非常重要的功能就是负责管理 RequestManager 的生命周期,RequestManager 的生命周期对应的就是 with() 方法中传入的 Android 组件所关联的生命周期,Androidx 中使用 Lifecycle 来描述各种组件的生命周期,在 Glide 中也会借助它,如果不熟悉的同学可以去找找相关的资料。Glide 中的 RequestManager 的生命周期主要包含以下三种情况:

  • Application 对应的 RequestManager
  • FragmentActivity 对应的 RequestManager
  • Fragment 对应的 RequestManager

后续的源码分析我们也是针对于这三种情况。

Application 对应的 RequestManager

我们直接看 RequestManagerRetriever#getApplicationManager() 方法的实现:

Java 复制代码
  @NonNull
  private RequestManager getApplicationManager(@NonNull Context context) {
    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;
  }

applicationManager 可以理解为是一个单例,它只会创建一次,上面有两个非常重要的对象:ApplicationLifecycle()Lifecycle) 与 EmptyRequestManagerTreeNodeRequestManagerTreeNode)。Lifecycle 就是用来控制 RequestManager 的生命周期,而 RequestManagerTreeNode 是用来获取它的所有的子组件对应的 RequestManager(例如 FragmentActivity 中的 Fragment 对应的 RequestManager,后面会讲到)。

Java 复制代码
class ApplicationLifecycle implements Lifecycle {
  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    listener.onStart();
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    // Do nothing.
  }
}

final class EmptyRequestManagerTreeNode implements RequestManagerTreeNode {
  @NonNull
  @Override
  public Set<RequestManager> getDescendants() {
    return Collections.emptySet();
  }
}

ApplicationLifecycle 除了告知添加的 LifecycleListener onStart() 生命周期以外不会做任何事情,也就是它的生命周期就是整个应用的生命周期。
EmptyRequestManagerTreeNode 返回的子 RequestManager 也是空的,它不管理任何的子的 RequestManager

默认创建 RequestManagerfactoryDEFAULT_FACTORY

Java 复制代码
  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) {
          return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
      };

是直接创建的一个 RequestManager 对象,我们可以在 GlideBuilder 中设置我们自定义的 RequestManagerFactory

总的来说 Application 对应的 RequestManager 不会额外管理生命周期,也就是只要请求发送出去了,永远不会暂停,永远不会销毁。它也不会管理任何的子 RequestManager

FragmentActivity 对应的 RequestManager

我们看看 RequestManagerRetriever#get() 方法,如果传入 FragmentActivity 怎么处理:

Java 复制代码
  @NonNull
  public RequestManager get(@NonNull FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
      // 如果当前不是 UI 线程,直接使用 Application 的 RequestManager
      return get(activity.getApplicationContext());
    }
    assertNotDestroyed(activity);
    // 监听 Activity 是否渲染第一帧
    frameWaiter.registerSelf(activity);
    // 判断 Activity 当前是否可见
    boolean isActivityVisible = isActivityVisible(activity);
    Glide glide = Glide.get(activity.getApplicationContext());
    // 调用 `LifecycleRequestManagerRetriever#getOrCreate()` 方法来获取或者创建一个对应的 RequestManager。
    return lifecycleRequestManagerRetriever.getOrCreate(
        activity,
        glide,
        activity.getLifecycle(),
        activity.getSupportFragmentManager(),
        isActivityVisible);
  }

这里有一个比较重要的点就是如果调用 Glide#with() 方法的线程不是在 UI 线程,会直接使用 ApplicationRequestManager,也就意味着失去了 Glide 对请求的生命周期管理。 FrameWaiter 是用来监听 Activity 的第一帧是否已经渲染的,如果已经渲染后续的 BitmapConfig 可以使用 HARDWARE,反之就不可以。

最后使用 LifecycleRequestManagerRetriever#getOrCreate() 方法来获取或者创建一个对应的 RequestManager(后面我们再分析这个流程)。

如果我们的 RequestManagerRetriever#get() 方法传入的参数是 Context 对应也是有可能构建一个 FragmentActivtiyRequestManager 的。

Java 复制代码
  @NonNull
  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) {
        return get((FragmentActivity) context);
      } else if (context instanceof ContextWrapper
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

如果当前的 ContextFragmentActivity 那就使用 FragmentActivityRequestManager;如果是 ContextWrapper 那就获取到它的 BaseContext,然后递归执行当前的 get() 方法;其他情况直接使用 ApplicationRequestManager

前面说到最后获取 FragmentActivityRequestManager 会通过 LifecycleRequestManagerRetriever#getOrCreate() 方法(后面要讲到的 FragmentRequestManager 也是通过它来获取),LifecycleRequestManagerRetrieverRequestManagerRetriever 的构造函数中就初始化了。我们来看看 LifecycleRequestManagerRetriever#getOrCreate() 方法的实现:

Java 复制代码
  RequestManager getOrCreate(
      Context context,
      Glide glide,
      final Lifecycle lifecycle,
      FragmentManager childFragmentManager,
      boolean isParentVisible) {
    Util.assertMainThread();
    // 获取缓存
    RequestManager result = getOnly(lifecycle);
    if (result == null) {
      // 缓存为空,创建一个新的 RequestManager
      
      // 用 LifecycleLifecycle 来封装 androdix 中的 Lifecycle
      LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);
      // 通过 RequestManagerFactory 创建一个 RequestManager
      result =
          factory.build(
              glide,
              glideLifecycle,
              // 注意这个 RequestManagerTreeNode
              new SupportRequestManagerTreeNode(childFragmentManager),
              context);
      // 添加内存缓存        
      lifecycleToRequestManager.put(lifecycle, result);
      // 监听生命周期状态
      glideLifecycle.addListener(
          new LifecycleListener() {
            @Override
            public void onStart() {}

            @Override
            public void onStop() {}

            @Override
            public void onDestroy() {
               // 当 Lifecycle 已经执行 onDestroy() 生命周期后,将当前 RequestManager 从缓存中移除
               lifecycleToRequestManager.remove(lifecycle);
            }
          });
      if (isParentVisible) {
        result.onStart();
      }
    }
    return result;
  }
  
  RequestManager getOnly(Lifecycle lifecycle) {
    Util.assertMainThread();
    return lifecycleToRequestManager.get(lifecycle);
  }

上面参数的 Lifecycle 就是 FragmentActivity 对应的 Androidx 中的 Lifecycle(后面要讲到的 Fragment 也是一样的);参数中的 FragmentManager 就是对应的 FragmentActivity#getSupportFragmentManager() 方法返回(如果是 Fragment 就是 Fragment#getChildFragmentManager() 方法返回)。

当对应的 LifecycleRequestManager 在缓存中没有时,就需要创建一个,然后主要有以下的逻辑:

  1. 通过 androidx 中的 Lifecycle 来封装一个 LifecycleLifecycle 对象。
  2. 通过 RequestManagerFactory#build() 方法创建一个 RequestManager,然后把它添加到缓存中,监听 Lifecycle 生命周期,在 onDestory() 生命周期中将当前的 RequestManager 从缓存中移除。

我们看看 LifecycleLifecycle 的实现:

Java 复制代码
final class LifecycleLifecycle implements Lifecycle, LifecycleObserver {
  @NonNull
  private final Set<LifecycleListener> lifecycleListeners = new HashSet<LifecycleListener>();

  @NonNull private final androidx.lifecycle.Lifecycle lifecycle;

  LifecycleLifecycle(androidx.lifecycle.Lifecycle lifecycle) {
    this.lifecycle = lifecycle;
    lifecycle.addObserver(this);
  }

  @OnLifecycleEvent(Event.ON_START)
  public void onStart(@NonNull LifecycleOwner owner) {
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

  @OnLifecycleEvent(Event.ON_STOP)
  public void onStop(@NonNull LifecycleOwner owner) {
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

  @OnLifecycleEvent(Event.ON_DESTROY)
  public void onDestroy(@NonNull LifecycleOwner owner) {
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
    owner.getLifecycle().removeObserver(this);
  }

  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (lifecycle.getCurrentState() == State.DESTROYED) {
      listener.onDestroy();
    } else if (lifecycle.getCurrentState().isAtLeast(State.STARTED)) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }
}

LifecycleLifecycle 只是对 androidx 中的 Lifecycle 的简单封装,它只会监听 ON_STARTON_STOPON_DESTROY 三个生命周期状态,每次添加 listener 都会检查一下状态,并下发。LifecycleLifecycle 构造函数中将自己添加到 Lifecycle 中,如果已经执行过 onDestroy() 将自己从 Lifecycle 中移除,避免泄漏。

我们再来看看 SupportRequestManagerTreeNode 的实现:

Java 复制代码
  private final class SupportRequestManagerTreeNode implements RequestManagerTreeNode {
    private final FragmentManager childFragmentManager;

    SupportRequestManagerTreeNode(FragmentManager childFragmentManager) {
      this.childFragmentManager = childFragmentManager;
    }

    @NonNull
    @Override
    public Set<RequestManager> getDescendants() {
      Set<RequestManager> result = new HashSet<>();
      getChildFragmentsRecursive(childFragmentManager, result);
      return result;
    }

    private void getChildFragmentsRecursive(
        FragmentManager fragmentManager, Set<RequestManager> requestManagers) {
      List<Fragment> children = fragmentManager.getFragments();
      for (int i = 0, size = children.size(); i < size; i++) {
        Fragment child = children.get(i);
        getChildFragmentsRecursive(child.getChildFragmentManager(), requestManagers);
        RequestManager fromChild = getOnly(child.getLifecycle());
        if (fromChild != null) {
          requestManagers.add(fromChild);
        }
      }
    }
  }

上面的代码也是比较简单,通过 FragmentManager 来递归遍历所有的 FragmentRequestManager,然后返回给 getDescendants() 方法。

Fragment 对应的 RequestManager

我们再看看 RequestManagerRetriever#get() 方法如果传入的是 Fragment,我们来看看如何处理:

Java 复制代码
  @NonNull
  public RequestManager get(@NonNull Fragment fragment) {
    Preconditions.checkNotNull(
        fragment.getContext(),
        "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getContext().getApplicationContext());
    }
    if (fragment.getActivity() != null) {
      frameWaiter.registerSelf(fragment.getActivity());
    }
    FragmentManager fm = fragment.getChildFragmentManager();
    Context context = fragment.getContext();
    Glide glide = Glide.get(context.getApplicationContext());
    return lifecycleRequestManagerRetriever.getOrCreate(
        context, glide, fragment.getLifecycle(), fm, fragment.isVisible());
  }

上面的方法很简单,和 FragmentActivity 相比就是 FragmentManager 通过 Fragment#getChildFragmentManager() 方法来获取,对应的 LifecycleFragmentLifecycle,同样的也是调用的 LifecycleRequestManagerRetriever#getOrCreate() 方法来获取,这个方法我们在前面已经分析过了。

我们再来看看 RequestManagerRetriever#get() 方法如果传入的是 View 的情况:

Java 复制代码
  @NonNull
  public RequestManager get(@NonNull View view) {
    if (Util.isOnBackgroundThread()) {
      return get(view.getContext().getApplicationContext());
    }

    Preconditions.checkNotNull(view);
    Preconditions.checkNotNull(
        view.getContext(), "Unable to obtain a request manager for a view without a Context");
    Activity activity = findActivity(view.getContext());
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }

    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      return fragment != null ? get(fragment) : get((FragmentActivity) activity);
    }

    // Standard Fragments.
    return get(view.getContext().getApplicationContext());
  }

上面的代码也比较简单,我简单说明一下上面的代码:

  1. 查找对应 ViewActivity,如果没有直接使用 ApplicationRequestManager
  2. 如果查找到的 ActivityFragmentActivity,遍历它的所有 Fragment,去查找当前 View 是属于哪个 Fragment,如果能够找到 Fragment,那么就使用 FragmentRequestManager;如果不能找到 Fragment,就使用 FragmentActivityRequestManager
  3. 如果查找到的 Activity 不是 FragmentActivity,直接使用 ApplicationRequestManager

RequestManager 对生命周期的处理

先看看 RequestManager 的构造函数:

Java 复制代码
  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));

    // 通知 Glide 有新的 RequestManager.
    glide.registerRequestManager(this);

    if (Util.isOnBackgroundThread()) {
      // 如果是非 UI 线程,需要在 UI 线程添加生命周期监听
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      // 添加生命周期监听
      lifecycle.addListener(this);
    }
    // 将生命周期也下发至网络监听
    lifecycle.addListener(connectivityMonitor);
    
    // 获取请求监听
    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    // 获取默认的请求配置
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
  }

主要做了以下事情:

  1. 对网络进行监听,当网络状态由不可用变成可用时,执行请求重试。
  2. ReqestManager 添加对 Lifecycle 的监听(需要在 UI 线程添加)。
  3. 网络监听对象也会监听 Lifecycle 的生命周期。
  4. Glide 中获取请求监听。
  5. Glide 中获取默认的请求配置。

我们再来简单看看 RequestManager 在不同的生命周期中做了什么事情:

Java 复制代码
  @Override
  public synchronized void onStart() {
    // 恢复暂停的请求
    resumeRequests();
    // target 执行 onStart()
    targetTracker.onStart();
  }

  @Override
  public synchronized void onStop() {
    // target 执行 onStop()
    targetTracker.onStop();
    if (clearOnStop) {
      // 清除请求
      clearRequests();
    } else {
      // 暂停请求
      pauseRequests();
    }
  }

  @Override
  public synchronized void onDestroy() {
    // target 执行 onDestroy()
    targetTracker.onDestroy();
    // 清除请求
    clearRequests();
    requestTracker.clearRequests();
    // 移除 RequestManager 对生命周期监听
    lifecycle.removeListener(this);
    // 移除 ConnectivityMonitor 对生命周期的监听
    lifecycle.removeListener(connectivityMonitor);
    Util.removeCallbacksOnUiThread(addSelfToLifecycle);
    // 通知 Glide 移除 RequestManager
    glide.unregisterRequestManager(this);
  }

所谓的 target 就是下游处理请求成功后结果的处理方式,比如我们的通常就是把它渲染到 ImageView 上。targetTracker 就是用来管理他们的。而 requestTracker 就是用来管理网络请求的各种生命周期。

最后

通过阅读 Glide 生命周期管理的源码,我们能够得出以下的使用小细节:

  • 如果在非 UI 线程使用 Glide#with() 方法,Glide 将失去生命周期的管理。
  • 如果 Glide#with() 方法传递的是 Context,那么它会去查找对应的 FragmentActivity,如果没有找到 FragmentActivity 将失去生命周期的管理;如果找到了就会使用 FragmentActivity 的生命周期管理。
  • 如果 Glide#with() 方法传递的是 View,首先会去查找它是否是某个 Fragment 中的 View,如果能够找到,就使用 Fragment 的生命周期管理;如果没有找到 Fragment 那么就使用 FragmentActivity 的生命周期管理;其他情况失去生命周期管理。

针对 Glide 生命周期处理的特性我的建议:

  1. 如果需要生命周期管理,不要在后台线程调用 Glide#with() 方法。
  2. 为了提高一点点性能,Glide#with() 方法中最好传入 FragmentActivityFragment,因为传入其他的参数,需要额外的性能开销去查找他们对应的 RequestManager.
相关推荐
深海呐3 小时前
Android AlertDialog圆角背景不生效的问题
android
ljl_jiaLiang3 小时前
android10 系统定制:增加应用使用数据埋点,应用使用时长统计
android·系统定制
花花鱼3 小时前
android 删除系统原有的debug.keystore,系统运行的时候,重新生成新的debug.keystore,来完成App的运行。
android
落落落sss4 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
消失的旧时光-19436 小时前
kotlin的密封类
android·开发语言·kotlin
服装学院的IT男8 小时前
【Android 13源码分析】WindowContainer窗口层级-4-Layer树
android
CCTV果冻爽9 小时前
Android 源码集成可卸载 APP
android
码农明明9 小时前
Android源码分析:从源头分析View事件的传递
android·操作系统·源码阅读
秋月霜风10 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教11 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python