Glide 加载图片时,我们知道它会根据传入的上下文决定它的生命周期,如果传入的是 Activity 或 Fragment,那么如果页面隐藏或销毁时,图片还没从网络上获取成功,它会自己停止加载图片;该页面重新出现在前台时,会重新加载,那么 Glide 是怎么做到的呢?在 Activity 中添加一个 Fragment,Fragment 的生命周期会随着 Activity 的生命周期变化而变化;同样,Fragment 中也可以嵌套 Fragment。反应快的,看到这就反应过来了,Glide 其实就是通过 Fragment 来控制生命周期的。
Glide 的 with() 方法,会传入几种不同的形参,我们以 FragmentActivity 为例,
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
RequestManagerRetriever 是个单利,我们看看它对应的 get() 方法
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
这个方法中会先判断当前线程是否是UI线程,如果不是,则调用重载方法,参数为 Application;如果是UI线程,先检查 activity 是否被销毁,然后获取一个 FragmentManager,把它们作为参数,传入 supportFragmentGet() 方法中
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
这个方法中主要牵涉到两个对象:RequestManager 和 SupportRequestManagerFragment,看名字,一个是加载图片管理器,另外一个是对管理器提供支持的Fragment,先看看 getSupportRequestManagerFragment(fm) 方法
SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
这个方法逻辑比较简单,先从事务管理器中根据 TAG 来找对应的Fragment,如果为空,则从集合中查找,如果还没有,则创建一个,并添加到集合中,然后开启一个事物,把生成的Fragment添加进去,然后通过Handler发送一条消息,在Handler接收器中,把管理器从集合中移除,为什么这么做,感觉是在做多余的操作?我也是看了一片文章才明白,比如说同一个页面 onCreate() 中两个 ImageView a和b 同时用 Glide 来加载图片,都执行了 getSupportRequestManagerFragment() 方法,a执行时,管理器 findFragmentByTag()找TAG标签的Fragment为空,则执行下面操作,创建 SupportRequestManagerFragment 并添加到事物管理器中;此时b也进入了这个方法,由于a中向管理器中添加了Fragment,此时应该不为null吧?实际上,findFragmentByTag(FRAGMENT_TAG) 还是 null,为什么呢?因为事务管理器添加Fragment的 enqueueAction() 方法,也是通过 Handler 来执行具体的逻辑,那么此时,onCreate() 还在执行,事务管理器的中 Handler 操作的 Runnable,还在队列中等待,如果没有 pendingSupportRequestManagerFragments 这个集合临时存储数据,则 SupportRequestManagerFragment 会被重复创建,造成浪费,并且也不符合逻辑。
继续看 supportFragmentGet(Context context, FragmentManager fm) 方法,里面还有一个 RequestManager,它new出来的,并且把 context 和 current 中的对象当做参数传入构造方法中,并且也把创建好的 requestManager 设置到 SupportRequestManagerFragment 中,我们来看看 RequestManager 类
public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
this(context, lifecycle, treeNode, new RequestTracker(), new 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 (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 和 ConnectivityMonitorFactory; RequestManager 实现了 LifecycleListener 接口,所以添加到 lifecycle集合中,connectivityMonitor 也被添加到集合中,它又是什么呢? 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();
}
}
}
这里做了个判断,是否有获取网络信息状态的权限,如果有则返回 DefaultConnectivityMonitor,如果无,则返回 NullConnectivityMonitor,NullConnectivityMonitor 里面的方法都是空的,没有相应的回调;注意 DefaultConnectivityMonitor 类,里面的逻辑相对简单,比较好理解,但它的思路很赞,明明是个监听网络变化的广播,把事件回调出去就行了,但这里加个注册监听和取消监听的逻辑, onStart() 和 onStop() 方法,这两个方法是何时触发的,一会再说;注册广播后,网络有了变化,会做个简单的逻辑比较,然后通过 listener 把事件回调出去,这里的 listener 就是 RequestManager 中的 RequestManagerConnectivityListener,它构造里面还有个 RequestTracker
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();
}
}
}
也就是说网络变化,有网络后,最终还是执行 RequestTracker 的 restartRequests() 方法,看名字也是恢复请求。
RequestManager 中另外一个地方就是 lifecycle ,它是个接口,它把 RequestManager 和 ConnectivityMonitor 通过 addListener() 方法添加起来,我们看看它是什么?
SupportRequestManagerFragment 的 getLifecycle() 和 getRequestManagerTreeNode() 返回的值当做形参传入了 RequestManager 的构造方法中,
private final RequestManagerTreeNode requestManagerTreeNode = new SupportFragmentRequestManagerTreeNode();
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
// For testing only.
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
看代码,一个是 RequestManagerTreeNode,一个是 ActivityFragmentLifecycle,先看 ActivityFragmentLifecycle
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(LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
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();
}
}
}
它是一个生命周期管理器,用一个集合添加 LifecycleListener 对象,然后遍历,调用对应的回调方法;isStarted 和 isDestroyed 是记录回调状态的,
而 addListener(LifecycleListener listener) 方法中,添加 listener 时,根据这两个属性,判断当前管理器是处于哪一个阶段,直接执行相应的回调,写法比较巧。SupportRequestManagerFragment 中的 lifecycle 添加了各种回调,由于 Activity 切入前台或后台,或跳转其他页面, Fragment 自己的声明周期也会变化,所以
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (requestManager != null) {
requestManager.onLowMemory();
}
}
这里的 lifecycle 就是上面 RequestManager 中的 lifecycle,Fragment 生命周期变化,就会调用相应的方法,RequestManager 和RequestManagerConnectivityListener都实现了 LifecycleListener,它俩由 Fragment 控制。内存不足,Fragment也会触发 onLowMemory() 方法,此时调用了 requestManager 的 onLowMemory() 方法,而 RequestManager 中,则是调用 Glide 的方法,清除内存
public void onLowMemory() {
glide.clearMemory();
}
再看看 requestManagerTreeNode 这个集合,不太理解;rootRequestManagerFragment 则是判断是否是当前Fragment,
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
rootRequestManagerFragment = RequestManagerRetriever.get()
.getSupportRequestManagerFragment(getActivity().getSupportFragmentManager());
if (rootRequestManagerFragment != this) {
rootRequestManagerFragment.addChildRequestManagerFragment(this);
}
}
@Override
public void onDetach() {
super.onDetach();
if (rootRequestManagerFragment != null) {
rootRequestManagerFragment.removeChildRequestManagerFragment(this);
rootRequestManagerFragment = null;
}
}
也是随Fragment的声明周期控制的,由于 Fragment 可以嵌套 Fragment,所以就有上面的写法,getDescendantRequestManagerFragments() 方法是被 SupportFragmentRequestManagerTreeNode的方法调用的,它这里应该是获取属于自己子Fragment的RequestManager,用于 Fragment嵌套Fragment的情况,调用的地方是 RequestManager 中的 resumeRequestsRecursive() 方法, 我们可以在代码中直接调用 Glide.with(this).pauseRequestsRecursive();。这里大概知道怎么回事,不敢乱讲,怕说错,望有懂的大神指教。