深入解析Glide生命周期管理

}

synchronized (this) {

if (mDestroyed || mHost == null) {

throw new IllegalStateException(“Activity has been destroyed”);

}

if (mPendingActions == null) {

mPendingActions = new ArrayList();

}

mPendingActions.add(action);

if (mPendingActions.size() == 1) {

mHost.getHandler().removeCallbacks(mExecCommit);

mHost.getHandler().post(mExecCommit);

}

}

}

这里的mHost其实就是activity创建的,并且持有activity以及mMainHandler的引用,根据上述代码可以知道,其实绑定fragment的操作最终是通过主线程的handler发送消息处理的,我们假设这个消息为m2。然后**handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();这句代码发送的消息为m3。那么当Glide.with(this).load(url_1).into(mImageView_1);**这句代码执行这里时,消息队列有了变化:

但是m2这个消息并不会马上被处理,这是因为m1还有代码还没有执行完毕,也就是说这个fragment并不会马上被绑定,此时m1继续向下执行到第二句代码**Glide.with(this).load(url_2).into(mImageView_2);**当这句代码走到getRequestManagerFragment时,如果在m1时,我们不将fragment临时存储在pendingRequestManagerFragments中,由于m2还没有被处理,那么

RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);

必然是找不到这个fragment的,那么就会导致重新创建一个新的重复的fragment,并开启事务绑定,这显然是不合情理的,因为Glide需要保证rootFragment的唯一性,rootFragment即fragment依附或者没有fragment依附的activity所创建的最上层RequestManagerFragment。

接着往下看RequestManagerFragment的构造方法做了什么。

public RequestManagerFragment() {

this(new ActivityFragmentLifecycle());

}

直接创建一个ActivityFragmentLifecycle,这个类实际是一个生命周期回调的管理类,实现了Lifecycle接口。所有的LifecycleListener会添加到一个集合中,当RequestManagerFragment生命周期方法触发时,会调用ActivityFragmentLifecycle相应生命周期方法,这个方法然后再遍历调用所有LifecycleListener的生命周期方法,以onStart生命周期方法为例,RequestManagerFragment中:

public void onStart() {

super.onStart();

lifecycle.onStart();

}

然后ActivityFragmentLifecycle中:

void onStart() {

isStarted = true;

for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {

lifecycleListener.onStart();

}

}

2.0.2 rootRequestManagerFragment

上面UML图上,可以知道RequestManagerFragment还有一个rootRequestManagerFragment的成员变量,Glide每创建一个RequestManagerFragment,都会尝试实例化rootRequestManagerFragment,这个fragment即顶级的Activity所创建的RequestManagerFragment,相关代码:

public void onAttach(Activity activity) {

super.onAttach(activity);

rootRequestManagerFragment = RequestManagerRetriever.get()

.getRequestManagerFragment(getActivity().getFragmentManager());

if (rootRequestManagerFragment != this) {

rootRequestManagerFragment.addChildRequestManagerFragment(this);

}

}

@Override

public void onDetach() {

super.onDetach();

if (rootRequestManagerFragment != null) {

rootRequestManagerFragment.removeChildRequestManagerFragment(this);

rootRequestManagerFragment = null;

}

}

可以看到,不管当前的RequestManagerFragment是通过何种方式创建的,都会在OnAttach时,拿到当前所绑定的Activity的FragmentManager来初始化一个RequestManagerFragment,这个RequestManagerFragment有可能是自身,有可能已经被初始化过了,比如是通过with(Activity activity)的方式初始化的,那么很显然

RequestManagerRetriever.get().getRequestManagerFragment(getActivity().getFragmentManager());

这句代码拿到的会是自己本身,而如果是通过with(Fragment fragment)的形式创建的,rootRequestManagerFragment将指向当前fragment绑定到Activity所绑定的RequestManagerFragment,如果该Activity没有绑定过,那么会开启事务绑定一个RequestManagerFragment。并且如果自己不是rootRequestManagerFragment的话,那么将会把自己保存到rootRequestManagerFragment中的一个集合:

private void addChildRequestManagerFragment(RequestManagerFragment child) {

childRequestManagerFragments.add(child);

}

简而言之,Glide会为Activity创建一个RequestManagerFragment做为rootFragment,并保存该Activity底下所有Fragment(如果有的话)所创建的RequestManagerFragment。

2.0.3 RequestManagerTreeNode

RequestManagerFragment初始化时,还会初始化RequestManagerTreeNode,顾名思义,这个类是用来保存请求树节点的,比如一个Activity采用Viewpager + Fragment的形式,而里面的Fragment又是一个ViewPager + Fragment的形式,这个时候,假设其中一个RequestManagerFragment生命周期方法走了,怎么知道哪些RequestManagerFragment绑定的LifeCycle应该得到调用呢?理想的情况是,应该让绑定该RequestManagerFragment的Fragment所有的子Fragment的RequestManagerFragment的生命周期得到调用,比如如下场景中,Activity中各有两个Fragment,两个Fragment又各有两个子Fragment,在所有Fragment中,均通过with(this)的方式来加载图片,经过之前的分析我们可以知道的是,ROOT RMF 中会保存有6个RMF(RMF即RequestManagerFragment):

当如果F1 RMF生命周期做出反应时,因为RequestManagerFragment是无界面的,所以可以理解为F1的生命周期做出反应。我们希望F11和F12所绑定的RequestManagerFragment也要立即做出反应。但是F2以及其底下的RequestManagerFragment则不应响应对应生命周期事件,我们知道任何一个RequestManagerFragment可以通过rootRequestManagerFragment拿到这6个RMF,继而拿到其所对应的RequestManager,那么怎么去确定F11 RMF 和 F12 RMF呢?这就是RequestManagerTreeNode干的事情了,RequestManagerFragment中的非静态内部类FragmentRequestManagerTreeNode实现了RequestManagerTreeNode:

private class FragmentRequestManagerTreeNode implements RequestManagerTreeNode {

@Override

public Set getDescendants() {

Set descendantFragments = getDescendantRequestManagerFragments();

HashSet descendants =

new HashSet(descendantFragments.size());

for (RequestManagerFragment fragment : descendantFragments) {

if (fragment.getRequestManager() != null) {

descendants.add(fragment.getRequestManager());

}

}

return descendants;

}

}

这个类做的事情比较简单,调用外部类RequestManagerFragment的方法getDescendantRequestManagerFragments拿到所有的“后裔”Fragment,然后再取出它的RequestManager,然后集合装起来返回,这里的后裔在前面的例子中,指的就是F11 RMF 和 F12 RMF,看看getDescendantRequestManagerFragments是怎么拿到的F11和F12:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)

public Set getDescendantRequestManagerFragments() {

//如果自己是rootFragment,那么直接返回childRequestManagerFragments

if (rootRequestManagerFragment == this) {

return Collections.unmodifiableSet(childRequestManagerFragments);

} else if (rootRequestManagerFragment == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

// Pre JB MR1 doesn’t allow us to get the parent fragment so we can’t introspect hierarchy, so just

// return an empty set.

return Collections.emptySet();

} else {

HashSet descendants = new HashSet();

for (RequestManagerFragment fragment

//遍历取出rootFragment中的RMF,并获取到其parentFragment,找出后裔。
rootRequestManagerFragment.getDescendantRequestManagerFragments()) {

if (isDescendant(fragment.getParentFragment())) {

descendants.add(fragment);

}

}

return Collections.unmodifiableSet(descendants);

}

}

看看isDescendant方法是如何判断的:

private boolean isDescendant(Fragment fragment) {

Fragment root = this.getParentFragment();

while (fragment.getParentFragment() != null) {

if (fragment.getParentFragment() == root) {

return true;

}

fragment = fragment.getParentFragment();

}

return false;

}

依上面的例子,当遍历到F11 RMF时,参数传递过来的是F11,root 则为F1,F11再拿到parent,也是F1,返回true,F12 RMF类似也返回true;

当遍历到F21 RMF时,参数传入F21,root仍是F1,此时F21再怎么拿Parent也不可能是root,返回false。

简而言之,RequestManagerTreeNode用来获取绑定该RequestManagerFragment的Fragment的所有子Fragment所绑定的RequestManagerFragment所绑定的RequestManager

2.0.4 RequestManager

上面一直在说RequestManagerFragment,下面回到FragmentGet方法中,再贴一次,免得上翻麻烦:

RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {

//获取RequestManagerFragment,并获取绑定到这个fragment的RequestManager

RequestManagerFragment current = getRequestManagerFragment(fm);

RequestManager requestManager = current.getRequestManager();

if (requestManager == null) {

//如果获取RequestManagerFragment还没有绑定过RequestManager,那么就创建RequestManager并绑定到RequestManagerFragment

requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());

current.setRequestManager(requestManager);

}

return requestManager;

}

根据上面的UML图,可以知道RequestManager是一个非常核心的类,并且还实现了LifecycleListener来处理请求的生命周期。上述代码在创建RequestManager时,传递了3个参数,分别是context,前面分析过的初始化RequestManagerFragment所创建的LifeCycle和RequestManagerTreeNode。直接看RequestManager的构造函数:

public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {

this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());

}

调用的另一个构造方法,并增加了两个新的参数RequestTracker和ConnectivityMonitorFactory。

RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,

RequestTracker requestTracker, ConnectivityMonitorFactory factory) {

this.context = context.getApplicationContext();

this.lifecycle = lifecycle;

this.treeNode = treeNode;

this.requestTracker = requestTracker;

this.glide = Glide.get(context);

this.optionsApplier = new OptionsApplier();

ConnectivityMonitor connectivityMonitor = factory.build(context,

new RequestManagerConnectivityListener(requestTracker));

// If we’re the application level request manager, we may be created on a background thread. In that case we

// cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding

// ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.

if (Util.isOnBackgroundThread()) {

new Handler(Looper.getMainLooper()).post(new Runnable() {

@Override

public void run() {

lifecycle.addListener(RequestManager.this);

}

});

} else {

lifecycle.addListener(this);

}

lifecycle.addListener(connectivityMonitor);

}

RequestTracker即所有请求操作的真正处理者,所有Request的暂停取消执行操作都由RequestTracker来完成,如RequestManager暂停请求的实现:

public void pauseRequests() {

Util.assertMainThread();

requestTracker.pauseRequests();

}

2.0.5 网络状态监测

请求生命周期的实现细节后面再说,暂时埋坑,先来看看ConnectivityMonitorFactory这个工厂生产了什么。

public class ConnectivityMonitorFactory {

public ConnectivityMonitor build(Context context, ConnectivityMonitor.ConnectivityListener listener) {

final int res = context.checkCallingOrSelfPermission(“android.permission.ACCESS_NETWORK_STATE”);

final boolean hasPermission = res == PackageManager.PERMISSION_GRANTED;

if (hasPermission) {

return new DefaultConnectivityMonitor(context, listener);

} else {

return new NullConnectivityMonitor();

}

}

}

很简单,接收一个ConnectivityListener根据是否有监控网络状态的权限来创建相应的网络监控器。

DefaultConnectivityMonitor也比较简单,就是内部定义了一个广播接收者,并且也实现了lifeCycleListener。在上面RequestManager的构造方法中,创建了一个RequestManagerConnectivityListener:

private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {

private final RequestTracker requestTracker;

public RequestManagerConnectivityListener(RequestTracker requestTracker) {

this.requestTracker = requestTracker;

}

@Override

public void onConnectivityChanged(boolean isConnected) {

if (isConnected) {

requestTracker.restartRequests();

}

}

}

这个listener很简单,收到网络状态连接就重启请求。然后通过工厂创建出了DefaultConnectivityMonitor,并把它添加到了lifecycle中。到这里,Glide监测网络状态来重启请求的实现方式就呼之欲出了,大体步骤如下:

在相应的生命周期方法中,会调用lifecycle的生命周期方法,lifecycle会调用DefaultConnectivityMonitor所实现的相应生命周期方法来注册及解除注册网络状态的广播接收者,收到广播后,会回调之前传递的参数ConnectivityListener的onConnectivityChanged方法来处理Request。

2.0.6 内存状态监测

RequestManager中还存有Glide这个入口类的实例,构造方法中直接获取到的,用来对内存状态的变更作出处理,比较简单,看看流程便可以了,以onTrimMemory为例,

当RequestManagerFragment的onTrimMemory被调用时,会调用其绑定的RequetManager的相应方法来处理:

@Override

public void onTrimMemory(int level) {

// If an activity is re-created, onTrimMemory may be called before a manager is ever set.

// See #329.

if (requestManager != null) {

requestManager.onTrimMemory(level);

}

}

然后RequestManager再调用Glide入口类的trimMemory来释放更多内存:

public void onTrimMemory(int level) {

glide.trimMemory(level);

}

2.0.7 生命周期回调流程总结

写在最后

由于本文罗列的知识点是根据我自身总结出来的,并且由于本人水平有限,无法全部提及,欢迎大神们能补充~

将来我会对上面的知识点一个一个深入学习,也希望有童鞋跟我一起学习,一起进阶。

提升架构认知不是一蹴而就的,它离不开刻意学习和思考。

**这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家,**梳理了多年的架构经验,筹备近1个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

最近还在整理并复习一些Android基础知识点,有问题希望大家够指出,谢谢。

希望读到这的您能转发分享和关注一下我,以后还会更新技术干货,谢谢您的支持!

转发+点赞+关注,第一时间获取最新知识点

Android架构师之路很漫长,一起共勉吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
glide.trimMemory(level);

}

2.0.7 生命周期回调流程总结

写在最后

由于本文罗列的知识点是根据我自身总结出来的,并且由于本人水平有限,无法全部提及,欢迎大神们能补充~

将来我会对上面的知识点一个一个深入学习,也希望有童鞋跟我一起学习,一起进阶。

提升架构认知不是一蹴而就的,它离不开刻意学习和思考。

**这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家,**梳理了多年的架构经验,筹备近1个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

[外链图片转存中…(img-WHYIWr6J-1715338065505)]

[外链图片转存中…(img-RDiasaa4-1715338065505)]

最近还在整理并复习一些Android基础知识点,有问题希望大家够指出,谢谢。

希望读到这的您能转发分享和关注一下我,以后还会更新技术干货,谢谢您的支持!

转发+点赞+关注,第一时间获取最新知识点

Android架构师之路很漫长,一起共勉吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值