初衷
Glide.with(ctx).load(res).into(view)
这是一行我们写的熟了不能再熟的代码,但是这简单的一句链式调用背后究竟发生了什么呢,同时为了准备一下即将到来的面试,让我们一起看一下
with(ctx)
image.png返回给了我们一个RequestManager,字面上的意思,就是图片请求管理器,
既然是manager,那么他的管理范围到底是多大呢,是一个Fragment,一个activity,还是全局呢,我们接着向下看
image.png
image.png
首先是单例获取全局唯一Glide对象,这里有一个annotationGeneratedModule,这个对象就是我们平时自定义的GlideModule,就是在这里初始化的,接着我们去看看RequestMangerRetriever这个类的方法
image.png
我们会发现里面有许多get(Activity),get(Fragment),find(Activity),find(Fragment)而返回值刚好是RequestManger,看到这里,我们就可以大胆猜测,一个RequestManager会管理一个Fragment或者一个Activity内的图片请求,那么RequestManager是怎么感知声明周期呢?我们回到getRetriever(ctx).get(ctx)方法 image.png
首先会按照context的不同类型执行不同参数的get重载方法,如果是不在主线程或者是ApplicationContext,就会使用全局的RequestManager,图片的生命周期就会和application保持同步,内存得不到及时回收。反之,如果我们有一张全局图片(比如WindowBackground),我们就可以利用这一特点提高效率,节约内存
image.png
public RequestManager get接受Activity,Fragment,View等参数,如果.with方法传入的是fragment,参数fm就会传入getChildFragmentManager,而如果是view,则会搜索出view对应的fragment,再继续调用参数为Fragment的get函数
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
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;
}
接着我们进入核心方法getSupportRequestManagerFragment,首先会判断是否已经存在和此fragment关联的SupportRequestManagerFragment,没有的话则去创建,因为Fragment的add是post执行的,所以为了保证不重复实例化Fragment,先把SupportRequestManagerFragment存入pendingSupportRequestManagerFragments集合中,收到ID_REMOVE_SUPPORT_FRAGMENT_MANAGER的handler消息后,会立即移除这个Fragment,因为已经能保证findFragmentByTag获取出来不为null了,然后我们再看看parentHint的作用
* Sets a hint for which fragment is our parent which allows the fragment to return correct
* information about its parents before pending fragment transactions have been executed.
*/
void setParentFragmentHint(@Nullable Fragment parentFragmentHint) {
this.parentFragmentHint = parentFragmentHint;
if (parentFragmentHint == null || parentFragmentHint.getContext() == null) {
return;
}
FragmentManager rootFragmentManager = getRootFragmentManager(parentFragmentHint); //获取顶层FragmentManager
if (rootFragmentManager == null) {
return;
}
registerFragmentWithRoot(parentFragmentHint.getContext(), rootFragmentManager);
}
注释翻译成人话就是在子fragment的声明周期未真正执行前,提前获取父fragment的生命周期回调,总所周期,fragment事务是有延迟的。
private void registerFragmentWithRoot(
@NonNull Context context, @NonNull FragmentManager fragmentManager) {
unregisterFragmentWithRoot();
rootRequestManagerFragment =
Glide.get(context)
.getRequestManagerRetriever()
.getRequestManagerFragment(context, fragmentManager); //查找顶层Fragment对应的RequestManagerFragment,因为是顶层,parentHint参数为null,所以不会出现递归调用的情况
if (!equals(rootRequestManagerFragment)) { //如果当前的RequestManagerFragment不是root就讲当前加入childRequestManagerFragments集合
rootRequestManagerFragment.addChildRequestManagerFragment(this);
}
}
结合上面的分析,getSupportRequestManagerFragment其实干了两件事:1.创建SupportRequestManagerFragment,2.找到根Fragment对应的SupportRequestManagerFragment,并子Fragment的SupportRequestManagerFragment加入到根SupportRequestManagerFragment的childRequestManagerFragments集合中,同时,为了避免重复加入,集合也是用了Set容器。
我们接着看fragmentGet方法,创建完SupportRequestManagerFragment并关联上Root后,首次肯定是获取不到RequestManager的,就会创建并设置给这个SupportRequestManagerFragment
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);
}
生命周期回调
当我们的Fragment或activity发生生命周期变化的时候,对应的SupportRequestManagerFragment因为为子Fragment或者根Fragment,生命周期会同步发生调用,而RequestManager是lifecycler的实现类,于是会回调到RequestManager中的声明周期方法
SupportRequestManagerFragment.java
@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();
}
RequestManager.java
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
/**
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
写到这里,我发现中间讲registerFragmentWithRoot那一段有点多余,为什么要加入集合呢?当我们在调用Glide.with(ctx).pauseAllRequests();时,会找到activity对应的SupportRequestManagerFragment,也就是root,因为root中有childs的集合,所以会能达到pauseAll的效果。
网友评论