Glide的生命周期监听
惠猛 2022.03.24
Glide实现对所属activity或者fragment生命周期监听的方法是:通过一个隐形的fragment,嵌入到所要监听的fragment
或者activity中,当被监听的fragment或者activity生命周期发生变化时,该隐形的fragment的相关生命周期函数也会被调用,
这样就实现了对外部activity或者fragment的监听。在Activity内新建一个无UI的Fragment,这个特殊的Fragment
持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。
在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。
代码中,Glide通过with绑定要监听的对象。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 通过with,绑定Glide要监听的对象
Glide.with(this)
}
override fun onStart() {
super.onStart()
}
}
在Glide的源码中,with函数有众多的重载,这是为了保证确保能监听到各种activity或者fragment或者application。在这些重载中无一例外的以RequestManager为返回值类型,RequestManager是为了专门去请求加载图片的。这些重载中还无一类外的以return getRetriever.get作为返回值。
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 Fragment fragment) {
// androidx Fragment
return getRetriever(fragment.getContext()).get(fragment);
}
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
// app.Fragment
return getRetriever(fragment.getActivity()).get(fragment);
}
RequestManagerRetriever()
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
Glide用于监听所属activity/fragment的隐形fragment在getRetriever.get中产生,以Glide的with参数传入类型为Activity为例,其返回 return getRetriever(activity).get(activity);中的get方法如下所示:
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
Util.assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager(); // 在这里产生了 用于管理隐形fragment的管理器
return fragmentGet(activity, fm);// 在这里产生了 用于监听的隐形activity
}
}
但是需要注意的是,因为Glide的with参数可以把Context作为参数,所以可以把Application作为参数,但是在这种情况下,Glide将不会生成用于监听的fragment,这种情况的get方法如下:
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("你个货,传入的是 空的 context,要把你吊起来打...");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context); // 进入FragmentActivity的get函数
} else if (context instanceof Activity) {
return get((Activity) context); // 进入Activity的get函数
} else if (context instanceof ContextWrapper && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext()); // 继续递归寻找 匹配合适的
}
}
// 若上面的判断都不满足,即context为一个application
return getApplicationManager(context);
}
在getApplicationManager中没有生成隐形fragment。
private RequestManager getApplicationManager(@NonNull Context context) {
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
Glide glide = Glide.get(context.getApplicationContext());
applicationManager = new RequestManager(glide, new ApplicationLifecycle(), context.getApplicationContext());
}
}
}
return applicationManager;
}
还需要注意的是,当Glide的with函数在一个子线程中执行时,也不会生成隐形fragment。举例:如下代码,当检查出来在子线程时,将会把application作为context传给get,根据上面的分析,Glide将不会生成用于监听的fragment。
public RequestManager get(@NonNull Fragment fragment) {
// androidx
if (Util.isOnBackgroundThread()) {
//检查如果是在非主线程,则会调用get的参数类型为context的重载。
return get(fragment.getContext().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getContext(), fm);
}
}
到这里可以做一个简单的总结,当with的参数类型为fragment,activity(也可以包括view)时,将会生成用于监听的fragment,当with的参数类型为application,或者with在子线程中被使用,将不会生成用于监听的fragment。
上文中指出来了用于监听的隐形fragment,它的具体生成如下:
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm) {
// 1、从 FragmentManager 中获取 SupportRequestManagerFragment(隐形)
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
// 2、从该 空白Fragment 中获取 RequestManager
RequestManager requestManager = current.getRequestManager();
// 3、首次获取,则实例化 RequestManager
if (requestManager == null) {
// 这样做的目的是为了 一个Activity或Fragment 只能有一个 RequestManager】
// 3.1 实例化
Glide glide = Glide.get(context);
requestManager = new RequestManager(glide, current.getGlideLifecycle(), context);
// 3.2 设置 Fragment 对应的 RequestManager 空白的Fragment<--->requestManager
current.setRequestManager(requestManager);
}
return requestManager;
}
在上面代码中 在注释1处拿到了监控该fragment隐形fragment,注重分析这个步骤: SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
// 1、从 FragmentManager 中获取 RequestManagerFragment
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm) {
// 第二次:就不会为null
// 1.1 尝试获取 FRAGMENT_TAG 对应的 Fragment
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 这样做的目的是为了 一个Activity或Fragment 只能有一个 空白的Fragment 对应】
// 1.2 尝试从【记录保存】中获取 Fragment
current = pendingRequestManagerFragments.get(fm);
// 1.3 实例化 Fragment
if (current == null) {
// 1.3.1 创建对象 空白的Fragment
current = new RequestManagerFragment();
// 1.3.2 【记录保存】映射关系 进行保存
pendingRequestManagerFragments.put(fm, current);
// 1.3.3 提交 Fragment 事务 同学们说:commitNow会抛出异常
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
// 1.3.4 post 一个消息
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
以上代码有一个重要的作用,就是当在一个activity或者fragment中多次调用Glide.with()方法时,该actiivity/fragment值会生成一个用于监听的隐形fragment,而一个隐形fragment对应一个RequestManager,这样的话 一个被监听的activity/fragment对应一个RequestManager。在上面你的代码中这种唯一的关系的第一个保证是通过map来保证,第二个是通过handler机制(我不理解). 再补充一点,在保存隐形fragment的map中,key为被监听activity/fragment 的fragmentmanager,value为 保存的就时用于监听的隐形fragment。
是为什么说SupportRequestManagerFragment是个隐形的fragment呢?如下:首先因为它继承自Fragment,所以它是个fragment,其次它除了相关的生命周期函数,没有视图,没有其他的,所以说它是隐形的。
// andrid x 隐形的Fragment 监听生命周期变化的
public class SupportRequestManagerFragment extends Fragment {
private static final String TAG = "SupportRMFragment";
private final ActivityFragmentLifecycle lifecycle;
@Nullable private RequestManager requestManager;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
@NonNull
public ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
@Nullable
public RequestManager getRequestManager() {
return requestManager;
}
// 相关生命周期函数
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
// this.lifecycle.addListener(requestManager);
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
}
在上面代码中,可以注意到的是 在onStart,onStop ,onDestroy方法中调用了lifecycle的相关方法,lifecycle是个接口,如下:接口中有两个方法,分别是添加监听和移除监听。
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
接口Lifecycle有两个实现类,分别是 ActivityFragmentLifecycle,ApplicationLifecycle,这其实分别对应了前文所说的是否生成隐形fragment的两种情况。
// 非Applicatoin作用域 绿色色领域 只有他有资格 搞一个隱形的Fragment来监听
public 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(); // 首次启动:会默认 onStop 先停止 然后再onStart
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onDestroy();
}
}
}
// Applicatoin作用域 红色领域
public class ApplicationLifecycle implements Lifecycle {
@Override
public void addListener(@NonNull LifecycleListener listener) {
/**
* APP起来了,APP起来的时候,执行onStart
*/
/**
* 子线程中,在实例化 RequestManager的时候,会执行 this.lifecycle.addListener(this);
* 此时,由于是子线程,无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
* 所以 只能是在addListener时,手动的onStart了
*/
listener.onStart();
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
// 我也没法做事情,APP死亡 我就跟随
// Do nothing.
/**
* 子线程中,由于无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
* 那么只能是属于 全局大范围的跟随App进程的灭亡,而灭亡了,所以啥事也不干了...
*/
}
}
`
在ApplicationLifecycle 和 ActivityFragmentLifecycle中众多方法中 有一个重要的参数 LifecycleListener ,LifecycleListener是一个接口:如下,可以看到在这个接口中有我们熟悉的onStart,onStop,onDestroy这些方法,
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
RequestManager实现了这个接口: 下面 只是主线机制
public class RequestManager implements LifecycleListener {
private Lifecycle lifecycle;
public RequestManager(Glide glide, Lifecycle lifecycle, Context applicationContext) {
this.lifecycle = lifecycle;
this.lifecycle.addListener(this); // 构造函数 已经给自己注册了【自己给自己绑定】
}
// Activity/Fragment 可见时恢复请求 (onStart() ) 掉用函数
@Override
public void onStart() {
....
Log.d(LOG.TAG, "开始执行生命周期业务 onStart: 运行队列 全部执行,等待队列 全部清空 ....");
....
}
// Activity/Fragment 不可见时暂停请求 (onStop() ) 掉用函数
@Override
public void onStop() {
....
Log.d(LOG.TAG, "开始执行生命周期业务 onStop: 运行队列 全部停止,把任务都加入到等待队列 ....");
.....
}
@Override
public void onDestroy() {
Log.d(LOG.TAG, "开始执行生命周期业务 onDestroy: 自己负责移除自己绑定的生命周期监听,释放操作 ....");
this.lifecycle.removeListener(this); // 已经给自己销毁了 【自己给自己移除】
}
}
以ActivityFragmentLifecycle 为例 他们的关系可以用下图描述: 可以观察到的是ActivityFragmentLifecycle 的作用范围往往是 一个fragment或者activity的一个生命周期
而ApplicationLifecycle和上面的流程类似 ,比不过相比于ActivityFragmentLifecycle ,ApplicationLifecycle的作用范围则是 整个应用的生命周期。
public class ApplicationLifecycle implements Lifecycle {
@Override
public void addListener(@NonNull LifecycleListener listener) {
/**
* APP起来了,APP起来的时候,执行onStart
*/
/**
* 子线程中,在实例化 RequestManager的时候,会执行 this.lifecycle.addListener(this);
* 此时,由于是子线程,无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
* 所以 只能是在addListener时,手动的onStart了
*/
listener.onStart();
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
// 我也没法做事情,APP死亡 我就跟随
// Do nothing.
/**
* 子线程中,由于无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
* 那么只能是属于 全局大范围的跟随App进程的灭亡,而灭亡了,所以啥事也不干了...
*/
}
}
总结一下当前遇到的几个核心类:
几个核心类介绍
通过对Glide生命周期绑定和传递整个流程过了一遍之后,大家应该对整体实现的框架有一定的了解。现在再来看下面一些核心类的介绍,应该更加有感触。
- Glide:库提供对外调用方法的类,传入页面引用。
- RequestManagerRetriever:一个处理中间类,获取RequestManager和RequestManagerFragment,并将两者绑定
- RequestManagerFragment:无UI的fragment,与RequestManager绑定,感知并传递页面的生命周期
- RequestManager:实现了LifeCycleListener,主要作用为结合Activity或Fragment生命周期,对Request进行管理,如pauseRequests(), resumeRequests(), clearRequests()。
- LifecycleListener:接口,定义生命周期管理方法,onStart(), onStop(), onDestroy(). RequestManager实现了它。
- ActivityFragmentLifecycle:保存fragment和Requestmanager映射关系的类,管理LifecycleListener, 空白Fragment会回调它的onStart(), onStop(), onDestroy()。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l4gVzxS2-