Glide源码分析-生命周期管理

声明:我目前分析的源码是最新的Glide源码:4.12.0版本

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

1. Glide简介

Glide是一个支持拉取,解码和展示视频快照,图片,和GIF动画的框架,正如它的名字翻译一样:滑翔。让用户加载任何形式的图片列表尽可能地变得更快、更平滑。

Glide 使用简明灵活的流式语法API,允许你在大部分情况下一行代码搞定需求:

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

默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。

2. 性能

Glide 充分考虑了Android图片加载性能的两个关键方面:

  • 图片解码速度

  • 解码图片带来的资源压力

为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:

  • 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
  • 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
  • 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

3. 源码分析

关于Glide的详细使用介绍,参见前面链接即可,但是分析源码也要有个开始吧,那我们就从最基本的用法入手,Glide最基本的用法就是三段论:with、load和into。那我们现在就先从with开始。

3.1 生命周期的作用域(1.Application, 2.Activity, 3.Fragment)

//com.bumptech.glide.Glide.java
public static RequestManager with(@NonNull Context context) {
    // getRetriever(context)返回RequestManagerRetriever,下面的生命周期关联会用到
    return getRetriever(context).get(context);
}

public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
}

public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
}

public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getContext()).get(fragment);
}

public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
}

从Glide.with()静态方法中,我们可以看到方法可以传入5个参数:Context、Activity、FragmentActivity、Fragment或者View。按照作用域分,我们可以把它分成两类:Application类和非Application类。

  • Application类:它的生命周期是全局的,没有空白Fragment就绑定Activity/Fragment。
  • 非Application类,它的生命周期跟随Activity和Fragment的生命周期,专门有一个空白Fragment绑定Activity/Fragment。

从上面with的重载方法看出都会调用到getRetriever()方法,他其实最终就是返回RequestManagerRetriever对象,紧接着,我们看看RequestManagerRetriever的get方法。这里先分两个来看:

  • Activity、FragmentActivity、Fragment和View
  • Context
3.1.1 Activity类的get()
public RequestManager get(@NonNull Activity activity) {
  if (Util.isOnBackgroundThread()) {
       //如果不是UI线程,生命周期划分到Application
    return get(activity.getApplicationContext()); 
  } else if (activity instanceof FragmentActivity) {
    return get((FragmentActivity) activity);
  } else {
    assertNotDestroyed(activity);
    frameWaiter.registerSelf(activity);
    android.app.FragmentManager fm = activity.getFragmentManager();
    // 不管是Activity、FragmentActivity、Fragment和View的get(),最终都会调用到fragmentGet()
    return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
  }
}
//最终with返回绑定了代理Fragemnt的RequestManager
private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //创建一个没有UI的空Fragment来监控用户自定义的Activity生命周期
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      //创建Glide实例
      Glide glide = Glide.get(context);
      //绑定Glide和空白的Fragemnt
      //注意!!:这里创建RequestManager的时候会传入Lifecycle,后面会根据这个lifecycle来透传fragment的生命周期给Glide
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
3.1.2 Context类的get()
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)) {
    // 如果在UI线程,并且是3.1.1小节的组件,就调用Activity类的get(),返回绑定了空Fragment的requestManager
    if (context instanceof FragmentActivity) {
      return get((FragmentActivity) context);
    } else if (context instanceof Activity) {
      return get((Activity) context);
    } else if (context instanceof ContextWrapper
        && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
      return get(((ContextWrapper) context).getBaseContext());
    }
  }
  // 作用域是Application返回的返回绑定了空Fragment的requestManager
  return getApplicationManager(context);
}

private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          //生命周期和Application一致
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
    return applicationManager;
  }
3.1.3 小结

Glide的with()生命周期总结如下图

作用域总结.png
  • 子线程中Glide调用get()、传入ApplicationContext和ServiceContext,对应的生命周期属于Application域,生命周期和Application一致
  • Activity、Fragment和View对应的生命周期是被代理Fragemnt监控的,Glide内部逻辑会根据Activity的生命周期做相应调整

3.2 Glide生命周期感知过程

如3.1.1小节中分析的,不管with传入的是fragment、Activity还是View,RequestManagerRetriever都会创建一个没有UI的Fragment(SupportRequestManagerFragment)来当代理,当用户自定义的Activity或者Fragment生命周期发生变化的时候,Glide内部可以通过代理Fragment知道生命周期发生的变化,因此内部也做相应的处理。例如下载并且加载是一个比较耗时操作,如果下载完成之后,Activity已经被销毁了,那就不用加载了,所有这就是Glide感知组件生命周期的意义,用户不用主动调用clear()方法来释放资源了。关联关系如下图。

生命周期与组件关联.png

3.3 Glide与空Fragment绑定过程

从3.1.3小结中可以知道,只有在主线程中调用with()并且传入Activity或者Fragment会绑定空Fragment。当传入的activity,这个activity上覆盖的空Fragment是RequestManagerFragment;当传入的是fragment,覆盖在上面的空fragment是SupportRequestManagerFragment。逻辑都是一样的,下面以传入fragment来分析。

/** Pending adds for SupportRequestManagerFragments. 
* 空Fragment(SupportRequestManagerFragment)与FragmentManager的映射关系
*/
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments = new HashMap<>();

private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
    // 从三个地方去拿空Fragment,紧接着会分析
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
    // 从空Fragment中拿到requestManager
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // 实例化glide用于在创建requestManager的时候绑定glide
      Glide glide = Glide.get(context);
      // 创建requestManager并且绑定glide
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      //如果父fragment可见,就通知glide的onStart()
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
}

private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
    // 第一个地方:先从FragmentManager中去拿
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      // 第二个地方:从内存中去拿
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
        //以上两个地方都没有,就创建一个空Fragment然后返回
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        //记录映射关系在内存中,临时存的
        pendingSupportRequestManagerFragments.put(fm, current);
        //提交Fragment事务
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //如果提交成功之后就删除临时存的映射关系
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

从supportFragmentGet()方法中我们看到了Glide内部逻辑和空Fragment的绑定过程。

不知道大家有没有疑惑:为什么在getSupportRequestManagerFragment()方法中要在pendingSupportRequestManagerFragments中临时保存空Fragment?

其实就是为了避免 SupportRequestManagerFragment 在一个作用域中重复创建。
因为commitAllowingStateLoss() 是将事务 post 到消息队列中的,也就是说,事务是异步处理的,而不是同步处理的。假设没有临时保存记录,一旦在事务异步等待执行时调用了Glide.with(...) ,就会在该作用域中重复创建 Fragment。

3.4 生命周期的详细监听过程

从上面小节分析可以看出,生命周期的管理,主要对Activity、Fragment和View(实质也是Activity或Fragment)有效,其他的都是Application域,没必须分析。所以后面的分析都是基于Activity或者Fragment的生命周期,而这两个逻辑都是一样的,我们还是以Fragment的分析为例。

从前面看出,每个Activity或者Fragment域都会创建一个空Fragment盖在上面。下来我们就从这个空Fragment开始分析Glide的生命周期是如何受影响的。Fragment盖的空Fragment是SupportRequestManagerFragment.java,那我们就从这里开始。

public class SupportRequestManagerFragment extends Fragment {
  private final ActivityFragmentLifecycle lifecycle;
    
  public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  @VisibleForTesting
  @SuppressLint("ValidFragment")
  public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
    
  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }
    
  ActivityFragmentLifecycle getGlideLifecycle() {
    return lifecycle;
  }
  ......  
}

从3.1.1小节可以看到,创建RequestManager时是通过工厂创建的,那我们在看看这个工厂

//RequestManagerRetriever.java中
//创建Glide实例
Glide glide = Glide.get(context);
requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);

//factory接口
public interface RequestManagerFactory {
    @NonNull
    RequestManager build(
        @NonNull Glide glide,
        @NonNull Lifecycle lifecycle,
        @NonNull RequestManagerTreeNode requestManagerTreeNode,
        @NonNull Context context);
  }

//默认的RequestManager工厂
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工厂在创建RequestManager的时候,传入了glide和lifecycle,在RequestManager中完成绑定。

public class RequestManager
    implements ComponentCallbacks2, 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;

      ......

      if (Util.isOnBackgroundThread()) {
        Util.postOnUiThread(addSelfToLifecycle);
      } else {
        //lifecycle的生命周期回调加入到RequestManager中
        lifecycle.addListener(this);
      }

      ......
    }
    
    public synchronized void onStart() {
        resumeRequests();
        // targetTracker维持着Traker列表,每个Traker属于Glide内部需要监听生命周期的逻辑
        targetTracker.onStart();
    }
    
    public synchronized void onStop() {
        pauseRequests();
        targetTracker.onStop();
    }
}

至此,生命周期的详细监听过程就通了。

总结:调用with()创建RequestManager,创建RequestManager传入Lifecycle对象(这个对象是在无界面 Fragment 中创建的),RequestManager通过Lifecycle通知Glide内部的各个业务Traker。

当 Fragment 的生命周期变化时,无界面 Fragment会感知到生命周期变化,然后通过Lifecycle 对象将事件分发到 RequestManager,RequestManager的onStart()将事件分发给targetTracker,targetTracker分发给Glide内部逻辑。

参考文档:

1.Glide简介

2.郭霖关于Glide的源码分析

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容