美文网首页
Glide源码--生命周期

Glide源码--生命周期

作者: wanweitong | 来源:发表于2021-02-20 17:16 被阅读0次

初衷

 Glide.with(ctx).load(res).into(view)

这是一行我们写的熟了不能再熟的代码,但是这简单的一句链式调用背后究竟发生了什么呢,同时为了准备一下即将到来的面试,让我们一起看一下

with(ctx)

image.png

返回给了我们一个RequestManager,字面上的意思,就是图片请求管理器,
既然是manager,那么他的管理范围到底是多大呢,是一个Fragment,一个activity,还是全局呢,我们接着向下看


image.png
image.png

首先是单例获取全局唯一Glide对象,这里有一个annotationGeneratedModule,这个对象就是我们平时自定义的GlideModule,就是在这里初始化的,接着我们去看看RequestMangerRetriever这个类的方法


image.png
我们会发现里面有许多get(Activity),get(Fragment),find(Activity),find(Fragment)而返回值刚好是RequestManger,看到这里,我们就可以大胆猜测,一个RequestManager会管理一个Fragment或者一个Activity内的图片请求,那么RequestManager是怎么感知声明周期呢?我们回到getRetriever(ctx).get(ctx)方法 image.png
首先会按照context的不同类型执行不同参数的get重载方法,如果是不在主线程或者是ApplicationContext,就会使用全局的RequestManager,图片的生命周期就会和application保持同步,内存得不到及时回收。反之,如果我们有一张全局图片(比如WindowBackground),我们就可以利用这一特点提高效率,节约内存
image.png

public RequestManager get接受Activity,Fragment,View等参数,如果.with方法传入的是fragment,参数fm就会传入getChildFragmentManager,而如果是view,则会搜索出view对应的fragment,再继续调用参数为Fragment的get函数

  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(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;
  }

接着我们进入核心方法getSupportRequestManagerFragment,首先会判断是否已经存在和此fragment关联的SupportRequestManagerFragment,没有的话则去创建,因为Fragment的add是post执行的,所以为了保证不重复实例化Fragment,先把SupportRequestManagerFragment存入pendingSupportRequestManagerFragments集合中,收到ID_REMOVE_SUPPORT_FRAGMENT_MANAGER的handler消息后,会立即移除这个Fragment,因为已经能保证findFragmentByTag获取出来不为null了,然后我们再看看parentHint的作用

   * Sets a hint for which fragment is our parent which allows the fragment to return correct
   * information about its parents before pending fragment transactions have been executed.
   */
  void setParentFragmentHint(@Nullable Fragment parentFragmentHint) {
    this.parentFragmentHint = parentFragmentHint;
    if (parentFragmentHint == null || parentFragmentHint.getContext() == null) {
      return;
    }
    FragmentManager rootFragmentManager = getRootFragmentManager(parentFragmentHint); //获取顶层FragmentManager
    if (rootFragmentManager == null) { 
      return;
    }
    registerFragmentWithRoot(parentFragmentHint.getContext(), rootFragmentManager);
  }

注释翻译成人话就是在子fragment的声明周期未真正执行前,提前获取父fragment的生命周期回调,总所周期,fragment事务是有延迟的。

private void registerFragmentWithRoot(
      @NonNull Context context, @NonNull FragmentManager fragmentManager) {
    unregisterFragmentWithRoot();
    rootRequestManagerFragment =
        Glide.get(context)
            .getRequestManagerRetriever()
            .getRequestManagerFragment(context, fragmentManager); //查找顶层Fragment对应的RequestManagerFragment,因为是顶层,parentHint参数为null,所以不会出现递归调用的情况
    if (!equals(rootRequestManagerFragment)) { //如果当前的RequestManagerFragment不是root就讲当前加入childRequestManagerFragments集合
      rootRequestManagerFragment.addChildRequestManagerFragment(this);
    }
  }

结合上面的分析,getSupportRequestManagerFragment其实干了两件事:1.创建SupportRequestManagerFragment,2.找到根Fragment对应的SupportRequestManagerFragment,并子Fragment的SupportRequestManagerFragment加入到根SupportRequestManagerFragment的childRequestManagerFragments集合中,同时,为了避免重复加入,集合也是用了Set容器。
我们接着看fragmentGet方法,创建完SupportRequestManagerFragment并关联上Root后,首次肯定是获取不到RequestManager的,就会创建并设置给这个SupportRequestManagerFragment

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

生命周期回调

当我们的Fragment或activity发生生命周期变化的时候,对应的SupportRequestManagerFragment因为为子Fragment或者根Fragment,生命周期会同步发生调用,而RequestManager是lifecycler的实现类,于是会回调到RequestManager中的声明周期方法

SupportRequestManagerFragment.java

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

RequestManager.java

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

写到这里,我发现中间讲registerFragmentWithRoot那一段有点多余,为什么要加入集合呢?当我们在调用Glide.with(ctx).pauseAllRequests();时,会找到activity对应的SupportRequestManagerFragment,也就是root,因为root中有childs的集合,所以会能达到pauseAll的效果。

相关文章

网友评论

      本文标题:Glide源码--生命周期

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