Glide生命周期探索

269 阅读3分钟

Glide生命周期探索

Glide官网中文版首页简介说到:

深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

上面写到Glide基于生命周期做了两件事情:

  • 优先处理活跃的请求

  • 必要时释放资源

Glide又是如何无侵入的获取生命周期的?

网上分析Glide的文章很多,都分析的很清晰,本文是自己分析过程的笔记

切入点

我们以最简单的用法作为切入点进行分析:

Glide.with(imageView).load(url).into(imageView)

追踪过程

绑定生命周期

先看with源码,发现返回了RequestManager,根据注释内容可以确定优先处理活跃的请求就是在此处完成的。它还实现了ComponentCallbacks2LifecycleListener,直接跳过去看:

public void onTrimMemory(int level) {
    if (level == TRIM_MEMORY_MODERATE && pauseAllRequestsOnTrimMemoryModerate) {
    // 暂停了所有请求
      pauseAllRequestsRecursive();
    }
  }

public synchronized void onStart() {
    // 恢复请求
    resumeRequests();
    targetTracker.onStart();
  }


public synchronized void onStop() {
    // 暂停请求
    pauseRequests();
    targetTracker.onStop();
  }

主要由两个类来完成,一个是RequestTracker(不关心),另一个是TargetTracker,注释写到用于持有当前活跃的Target,并且转发生命周期事件

Target又是什么?TargetTracker#track是唯一添加的调用,直接追踪调用:

return into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());

根据类型不同,返回结果是一个ImageViewTarget,注释写到用于显示resources到ImageView上,它的父类ViewTarget,注释写到用于加载Bitmap到View的默认实现类

关注点回到生命周期上,跟踪下TargetTracker#onXX的调用,矛头直指ActivityFragmentLifecycle,它也是简单的收集和转发生命周期。追踪下addListener,发现RequestManager确实有添加的过程,具体怎么添加,我们先不管。

发现ActivityFragmentLifecycle的生命周期,由两个Fragment分发(RequestManagerFragment、SupportRequestManagerFragment)ActivityFragmentLifecycle由构造函数注入,但是没有调用,很奇怪,追踪下对外暴露getGlideLifecycle的调用:

  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    ...
    requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      ...
    return requestManager;
  }

仅有一处,是在构造RequestManager时所用,原来是共用的同一个,也说明了每个ActivityFragmentLifecycle都对应一个RequestManager

并且通过传递的FragmentManager和一个Fragment创建了RequestManagerFragment

  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    ...
    current = new RequestManagerFragment();
    current.setParentFragmentHint(parentHint);
    pendingRequestManagerFragments.put(fm, current);
    // 添加到了fm中
    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
    ...
    return current;
  }

RequestManagerFragment被添加到了fm中,也就是说,Glide通过在fm中注入一个自己的Fragment来实现绑定生命周期的效果

无侵入

那么又是如何实现无侵入的?追踪下这个FragmentManager是怎么来的,最终都是回归到with方法,看看到底是怎么拿的:

public RequestManager get(@NonNull Activity activity) {
  ...
  android.app.FragmentManager fm = activity.getFragmentManager();
  return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}

public RequestManager get(@NonNull android.app.Fragment fragment) {
  ...
  android.app.FragmentManager fm = fragment.getChildFragmentManager();
  return fragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}

public RequestManager get(@NonNull View view) {
  ...
  Activity activity = findActivity(view.getContext());
  ...
  if (activity == null) {
    // 处理非activity的情况
    return get(view.getContext().getApplicationContext());
  }
  // 处理用户在FragmentActivity嵌套Support包内Fragment的情况
  if (activity instanceof FragmentActivity) {
    Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
    return fragment != null ? get(fragment) : get((FragmentActivity) activity);
  }
  // 处理Activity嵌套旧Fragment的情况
  android.app.Fragment fragment = findFragment(view, activity);
  if (fragment == null) {
    return get(activity);
  }
  return get(fragment);
}

public RequestManager get(@NonNull Context context) {
  ...
  // 不属于Fragment、Activity、FragmentActivity的情况
  return getApplicationManager(context);
}

ActivityFragment比较简单,继续看看ViewContext的情况:

  private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    ...
    applicationManager =
                factory.build(
                    glide,
                    new ApplicationLifecycle(),
                    new EmptyRequestManagerTreeNode(),
                    context.getApplicationContext());
    return applicationManager;
  }

Context的情况下,且不属于FragmentActivityFragmentActivity的情况,GlideApplicationLifecycle整个应用的生命周期传给了RequestManager也就是相当于是没有生命周期

  private Fragment findSupportFragment(@NonNull View target, @NonNull FragmentActivity activity) {
    tempViewToSupportFragment.clear();
    // 收集所有fragment的根View,和fragment组成map
    findAllSupportFragmentsWithViews(
        activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
    Fragment result = null;
    // 当前FragmentActivity的根view的容器
    View activityRoot = activity.findViewById(android.R.id.content);
    View current = target;
    while (!current.equals(activityRoot)) {
      result = tempViewToSupportFragment.get(current);
      if (result != null) {
        break;
      }
      if (current.getParent() instanceof View) {
        // 不断往上
        current = (View) current.getParent();
      } else {
        break;
      }
    }

    tempViewToSupportFragment.clear();
    return result;
  }

在嵌套的情况下,通过遍历当前Activity下的所有Fragment根View,找到和当前View根View匹配的Fragment,剩下流程和传入Fragment的流程相同