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()
方法中的参数可以是 Context
,FragmentActivity
,Fragment
,View
。RequestManagerRetriever
通过这些 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
) 与 EmptyRequestManagerTreeNode
(RequestManagerTreeNode
)。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
。
默认创建 RequestManager
的 factory
是 DEFAULT_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
线程,会直接使用 Application
的 RequestManager
,也就意味着失去了 Glide
对请求的生命周期管理。 FrameWaiter
是用来监听 Activity
的第一帧是否已经渲染的,如果已经渲染后续的 Bitmap
的 Config
可以使用 HARDWARE
,反之就不可以。
最后使用 LifecycleRequestManagerRetriever#getOrCreate()
方法来获取或者创建一个对应的 RequestManager
(后面我们再分析这个流程)。
如果我们的 RequestManagerRetriever#get()
方法传入的参数是 Context
对应也是有可能构建一个 FragmentActivtiy
的 RequestManager
的。
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);
}
如果当前的 Context
是 FragmentActivity
那就使用 FragmentActivity
的 RequestManager
;如果是 ContextWrapper
那就获取到它的 BaseContext
,然后递归执行当前的 get()
方法;其他情况直接使用 Application
的 RequestManager
。
前面说到最后获取 FragmentActivity
的 RequestManager
会通过 LifecycleRequestManagerRetriever#getOrCreate()
方法(后面要讲到的 Fragment
的 RequestManager
也是通过它来获取),LifecycleRequestManagerRetriever
在 RequestManagerRetriever
的构造函数中就初始化了。我们来看看 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()
方法返回)。
当对应的 Lifecycle
的 RequestManager
在缓存中没有时,就需要创建一个,然后主要有以下的逻辑:
- 通过
androidx
中的Lifecycle
来封装一个LifecycleLifecycle
对象。 - 通过
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_START
、ON_STOP
和 ON_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
来递归遍历所有的 Fragment
的 RequestManager
,然后返回给 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()
方法来获取,对应的 Lifecycle
是 Fragment
的 Lifecycle
,同样的也是调用的 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());
}
上面的代码也比较简单,我简单说明一下上面的代码:
- 查找对应
View
的Activity
,如果没有直接使用Application
的RequestManager
。 - 如果查找到的
Activity
是FragmentActivity
,遍历它的所有Fragment
,去查找当前View
是属于哪个Fragment
,如果能够找到Fragment
,那么就使用Fragment
的RequestManager
;如果不能找到Fragment
,就使用FragmentActivity
的RequestManager
。 - 如果查找到的
Activity
不是FragmentActivity
,直接使用Application
的RequestManager
。
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());
}
主要做了以下事情:
- 对网络进行监听,当网络状态由不可用变成可用时,执行请求重试。
ReqestManager
添加对Lifecycle
的监听(需要在 UI 线程添加)。- 网络监听对象也会监听
Lifecycle
的生命周期。 - 从
Glide
中获取请求监听。 - 从
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
生命周期处理的特性我的建议:
- 如果需要生命周期管理,不要在后台线程调用
Glide#with()
方法。 - 为了提高一点点性能,
Glide#with()
方法中最好传入FragmentActivity
和Fragment
,因为传入其他的参数,需要额外的性能开销去查找他们对应的RequestManager
.