本文将从源码的角度,分析Glide是如何关联生命周期的。
如无特殊说明,源码版本均指:4.6.1
学习Glide是如何关联生命周期的,核心在于一个知识点:
fragment
的生命周期,是与Activity
生命周期对应的。
明白并牢记这一点可,以更好的理解本文。
我们先以继承AppCompatActivity
(它的父类是FragmentActivity
)为例分析。在第3部分,我们再进行拓展到一般情况。
Glide
加载图片最基本的方式如下:
Glide.with(MainActivity.this).load(url).into(mImageView);
Glide
生命周期绑定是从入口单例类Glide
开始的,通过with()
多个重载方法来实现对生命周期的绑定工作。
这个方法有多个重载,可以传入Context
、Activity
、Fragment
、View
等,但是内部调用方法都是一样的,只是参数有所不同,这里以传入FragmentActivity
为例。
代码片1
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
第4行代码中, getRetriever(activity)
,返回的是 RequestManagerRetriever
第4行代码 整体看,即看 RequestManagerRetriever.class
中的get
方法:
代码片2 #RequestManagerRetriever.class
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
//如果是在子线程
if (Util.isOnBackgroundThread()) {
--->第2部分会分析(2A)
return get(activity.getApplicationContext());
} else {
//如果是在主线程
assertNotDestroyed(activity);
//获取当前Activity的FragmentManager
//用于后续将创建的Fragment绑定到activity
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null /*parentHint*/);
}
}
那我们看一下supportFragmentGet
方法:
代码片3 #RequestManagerRetriever.class
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
@Nullable Fragment parentHint) {
//创建无UI的fragment(第2部分分析),并绑定到当前activity
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); --->分析3A
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
//创建RequestManager,获取fragment的lifecycle,传入requestManager
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
我们看一下3A(代码片3第8行)的SupportRequestManagerFragment
是如何获取的。进入getSupportRequestManagerFragment
方法:
代码片4 #RequestManagerRetriever.class
// pendingSupportRequestManagerFragments是一个map集合
@VisibleForTesting
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
@NonNull
SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
//1、由FragmentManager通过tag获取fragment
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//2、从缓存集合中获取fragment的,map以fragmentManger为key,
//以fragment为value进行存储
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
//3、创建一个fragment实例
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); ---(第3部分会分析)分析4A
}
}
return current;
}
1、创建无UI
的Fragment
,并绑定到当前activity
;
2、通过builder
模式创建RequestManager
,并且将fragment
的lifecycle
传入,这样Fragment
和RequestManager
就建立了联系;
3、获取Fragment
对象,先根据tag
去找,如果没有从内存中查找,pendingSupportRequestManagerFragments
是一个存储fragment
实例的HashMap
,再没有的话就new
一个。
我们看一下SupportRequestManagerFragment
类具体是怎么样的?
代码片5 SupportRequestManagerFragment.class
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;
}
@NonNull
ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
@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();
}
//省略部分代码
}
RequestManagerFragment
的生命周期相关的函数调用lifecycle
对象对应的方法,而lifecycle
是在SupportRequestManagerFragment
构造函数数中创建的:
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
看一下ActivityFragmentLifecycle.class
类。
这个类实际是一个生命周期回调的管理类,实现了Lifecycle
接口。所有的LifecycleListener
会添加到一个集合中,当RequestManagerFragment
生命周期方法触发时,会调用ActivityFragmentLifecycle
相应生命周期方法,这个方法然后再遍历调用所有LifecycleListener
的生命周期方法。
Lifecycle.class
有且只有2个方法:
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
ActivityFragmentLifecycle
内部维持了生命周期的监听者列表:
代码片6 ActivityFragmentLifecycle.class
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}
}
当RequestManagerFragment
生命周期变化时,调用ActivityFragmentLifecycle
的对应生命周期方法,其实现就是遍历生命周期监听列表,并调用监听者对应的生命周期方法,比如上面的onStart()
、onStop()
、onDestroy()
方法。
那么什么时候添加监听者到ActivityFragmentLifecycle
呢?答案是创建RequestManager
的时候,我们看下RequestManager构成函数:
代码片7 RequestManager.class
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));
if (Util.isOnBackgroundThread()) {
//如果是子线程,则切换到主线程监听生命周期
mainHandler.post(addSelfToLifecycle);
} else {
//监听生命周期
lifecycle.addListener(this);
}
//生命周期变化时,相应的监听网络状态和取消监听网络装
lifecycle.addListener(connectivityMonitor);
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
当RequestManagerFragment
生命周期变化时,调用ActivityFragmentLifecycle
的对应生命周期方法。
而ActivityFragmentLifecycle
是在创建RequestManager
的时候添加的。
另外一方面,RequestManagerFragment
生命周期与Activity
生命周期一致。
进而,最终将Activity
生命周期与ActivityFragmentLifecycle
关联起来。
上面分析的,只是针对在 继承FragmentActivity
的Activity
中的情况.下面将对一般情况进行分析。
我们看一下Glide.with()
的构造方法:
代码片8 Glide.class
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
这个方法有多个重载,可以传入Context
、Activity
、Fragment
、View
等.但其实你会发现,上面所有getRetriever
全部是调用下面的代码:
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
最终都是Context
上下文接收。
但代码片8中get
方法却有一些不同.见RequestManagerRetriever.class
类
代码片9 RequestManagerRetriever.class
@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 Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null /*parentHint*/);
}
}
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(fragment.getActivity(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment);
}
}
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null /*parentHint*/);
}
}
@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());
// The view might be somewhere else, like a service.
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
// Support Fragments.
// Although the user might have non-support Fragments attached to FragmentActivity, searching
// for non-support Fragments is so expensive pre O and that should be rare enough that we
// prefer to just fall back to the Activity directly.
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
return fragment != null ? get(fragment) : get(activity);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
虽然有多个重载,但是总体上只有2种情况,即传入的是否为Application
类型参数。
传入Application
Context
或者在子线程使用:调用getApplicationManager(context)
;这样Glide
的生命周期就和应用程序一样了。
@NonNull
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) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
这里获取RequestManager
对象的方式和之前传入Activity
、Fragment
对象是有所区别的,之前是创建了一个SupportRequestManagerFragment
/RequestManagerFragment
对象,然后获取其内部创建的Lifecycle
对象作为参数传到RequestManager
;而这里的主要差异是获取Lifecycle
对象不一样,用的是ApplicationLifecycle
,由于没有创建Fragment
,这里只会调用onStart()
,这种情况Glide
生命周期就和Application
一样长了。
class ApplicationLifecycle implements Lifecycle {
@Override
public void addListener(@NonNull LifecycleListener listener) {
listener.onStart();
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
// Do nothing.
}
}
其它情况,比如传入Activity
、Fragment
等:最后只会调用fragmentGet()
、或者supportFragmentGet()
中的一个,这样Glide
就可以关联生命周期,会在生命周期不同的方法中对请求做不同的处理。
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
@Nullable Fragment parentHint) {
//创建无UI的Fragment,并绑定到当前activity
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
//创建RequestManager,获取fragment的lifecycle,传入requestManager
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//fragment与RequestManager关联
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
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;
}
2个方法等实现其实都是一样的,唯一的区别是supportFragmentGet
创建的是v4包下的Fragment
,fragmentGet
创建的是android.app.Fragment
。
而上述2段代码中的代码在一中第2部分 SupportRequestManagerFragment
类已经分析过了。
pendingSupportRequestManagerFragments
为什么添加fragment
后又移除?代码片4的代码再次贴出来:
代码片4 #RequestManagerRetriever.class
// pendingSupportRequestManagerFragments是一个map集合
@VisibleForTesting
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
@NonNull
SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
//1、由FragmentManager通过tag获取fragment
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
//2、从缓存集合中获取fragment的,map以fragmentManger为key,
//以fragment为value进行存储
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
//3、创建一个fragment实例
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); ---(第3部分会分析)分析4A
}
}
return current;
}
在第22行代码,将fragment(即fm)
添加到pendingSupportRequestManagerFragments
集合中,但第24行代码通过handler
移除代码:
private static final int ID_REMOVE_SUPPORT_FRAGMENT_MANAGER = 2;
@Override
public boolean handleMessage(Message message) {
// .....
//删除无关代码
switch (message.what) {
// .....
//删除无关代码
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
break;
}
// .....
//删除无关代码
return handled;
}
这里有个问题很奇怪,刚把创建的fragment
对象放入map
缓存起来,但是马上又通过handler
把它删除,这是为什么呢?
原因是这样的,当调用FragmentManager
的add()
方法时,是通过开启事务的方式来进行绑定的,这个过程是异步的,具体来说,就是调用add
方法时,并不是马上就和activity
绑定好了,而是通过Hander
来处理的。
下面来看一种应用场景:
@Override
protected void onStart() {
super.onStart();
Glide.with(this).load("xx").into(image1);
Glide.with(this).load("xx").into(image2);
}
(1)在第一次调用第一行代码的时候,会生成一个Fragment
对象,通过FragmentManager
出发Fragment
于Activity
绑定,这个绑定过程是通过Handler
发消息来完成的,假设这个消息为m1;
(2)紧接着使用Handler
来发送消息从HashMap
中删除刚才保存的Fragment
,假设这个消息为m2;
(3)由于是异步的,在消息未处理之前已经开始执行第二行Glide
代码了,具体说可能是m1,m2还没有处理,就已经开始调用getSupportRequestManagerFragment
方法了,这个方法内部是获取Fragment
对象的,具体分析上面说过了;如果不用map
来缓存fragment
,那么代码流程应该是这样的:
(本来的)
@NonNull
SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
(假如不用map来缓存fragment)
@NonNull
SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
return current;
}
此时通过findFragmentByTag
还没有找到Fragment
,就会重新生成一个Fragment
,这是Glide
所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的Fragment
存储到HashMap
中,这样就不会重复生成。等到SupportRequestManagerFragment
与Activity
绑定完成后,也就是消息m1处理完成后,再将Fragment
从Map
中销毁。
在Glide.with( )
传参数时,有以下建议:
(1)尽量传递fragment
或者activity
, 这样可以减少通过view
找到具体的fragment
或者activity
的步骤;
(2)尽量采用support
包下的fragment
/activity
;一是因为兼容性;二是如果统一使用support
包下的可以避免创建于与app
包下FragmentManager
管理的RequestManager
。
(3)在UI
线程中调用,可以避免RequestManager
生命周期与Application
的一致;也尽量减少使用Application
作为参数传递,也是同样的道理。
推荐阅读:
Glide解析三:Glide是如何自动感应生命周期的?
13.Glide源码分析1(生命周期关联)
Glide生命周期管理