0%

09-Glide-第一节课(最新Glide4.11源码阅读)

一、为何监听Activity/Fragment 生命周期

Glide 的使用很简单:

1
Glide.with(this).load().into(imageView)

其中的职责很简单:

  • with : 生命周期管理。传入 Activity 或者 Fragment 就会创建一个空白 Fragment 来监听生命周期,传入 Application Context 则不会

  • load:构建出 RequestBuilder 对象

  • into : 做了几件事情:1)运行队列、等待队列 2)活动缓存 3)内存缓存 4)网络模型

面试题:我们使用了 Glide.with(this).load().into 加载图片之后,在 Activity 的 onDestroy 中是不是要调用:Glide.with(this).clear(imageView) 来清理掉不用的 View 呢?

很多同学可能会回复这是必须的,但是事实上这不是必需的,因为 Glide 内部会有监听机制,在 Activity 的onDestroy 中会自动 clear 掉。

二、生命周期作用域

那么 Glide 是怎么做到自动 clear 呢?原理在于它会创建一个空白的 Fragment 来监控 Activity/Fragment 的生命周期变化

你可以发送很多的加载图片的request ,这些统一由 RequestManager 去管理。

如果在子线程使用 Glide 加载图片,即时你传入 Activity ,也是在 Application 作用域,这时候不会给你搞那个空白的 Fragment 。总结一下各种情况下根据 with 传入的参数而产生的生命周期作用域:

  • 在子线程:作用域为 Application

  • (在主线程)传入 ServiceContext/Application Context: 作用域为 Application

  • (在主线程)传入View:作用域为 Fragment 或者 Activity

  • (在主线程)传入 Fragment: 作用域为 Fragment

  • (在主线程)传入 Activity: 作用域为 Activity

所以也可以总结说 Application 作用域和非Application 作用域,这是根据是否创建空白 Fragment 监听生命周期这个动作来区分的

老师说学习开源框架最好的方式就是:先大概看一遍,然后仿照它的 API 开始自己写,把它所有的实现都简化:比如它是工厂模式创建对象,那我就直接 new 出来;假如它有各种判空,直接干掉,假如有复杂的条件判断,先干掉。实现最简单的,这样才能快速理解整个流程。

RequestManager 中,生命周期 onStart 的时候: 运行队列-全部开始执行;等待队列-全部清空;onStop 的时候: 运行队列-全部停止,所有任务添加到等待队列;

Glide 中设计很巧妙的一个点就是:Glide 需要保证一个 Activity 只能有一个空白 Fragment 来监听它的生命周期,那么在 RequestManagerRetriever 这个类中,就会写出看起来匪夷所思的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private RequestManagerFragment getRequestManagerFragment(FragmentManager fm, Fragment parentHint, boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}

创建了这个 fragment 需要将其放入map 中先保存起来,之后再 commit 这个 fragment ;再然后就通过 Handler 移除这个 fragment ,为什么这么做?

这是因为 fragment 做 commit 操作的时候,是通过主线程的 Handler 执行的,最后会体现在handler 往主线程发送了一个 Message,如果这个Message 还没执行,此时来了第二个请求,那么它通过 getTag 去获取这个 Fragment 是获取不到的,那么就会再创建一个,所以这里需要缓存下;那为什么在 commit 之后可以通过(主线程的) Handler 移除缓存的Fragment 呢?那么是因为 ,由于 commit 操作先执行,那么 commit 这个 Message 肯定在后续的移除 fragment 的这个 Message 之后,由于 Handler 是顺序执行这些 Message 的,所以执行移除操作的时候,commit 的那个 message 肯定已经执行过了,所以可以执行!

JetPack 的 Lifecycle 就是 模仿的 Glide 。Glide 的源码太庞大了。

有两个空白 Fragment ,一个是 Androidx 的 Fragment ,一个是 android.app 的 Fragment 。我们要注意区分。

三、生命周期回调

Fresco 看起来非常舒服,很容易看懂

但是 Glide 可能你看了一周源码,还是找不到网络请求的地方,看懂 Glide 的源码之后,再去看 Fresco 和 Picaso 都是很简单的事情。老师说是要研究半年才能给大家说这个事情。

老师说 RxJava 和 Okhttp 在 Glide 面前是小弟。这个也确实比较复杂

谢谢你的鼓励