原文链接:Glide核心设计一:皮皮虾,我们走
引言
皮皮虾,又名虾姑,是淡水中的强者。其头部的两个锤节,可以轻易破坏贝类的外壳,身体上的步足可以保证快速移动。这些优秀的品质,使它被表情包盯上。
Glide,作为Android最优秀的图片加载框架之一,能和Activity和Fragment的生命周期绑定,是区别于其它网络框架的核心特征,也是本文分析的重点。
我们将此特征和皮皮虾表情包做一个类比:
图片网络请求紧跟Activity、Fragment的生命周期,当页面不可交互时自动停止加载,当回到可交互状态时,继续加载。就像表情包(Activity、Fragment)控制皮皮虾(图片请求)一样。
框架设计
简单使用
Glide.with(Context).load(String).into(ImageView)可实现从网络中获取图片并展示到ImageView当中。其中和页面作生命周期绑定的主要入口是Glide.with(Context)。按照一般的分析逻辑应该先分析源码,才得出结论,但因一入源码深似海,不利于整体把握,所以先给出结论。Glide.with(Context)返回的是一个RequestManager,我们来看RequestManager的类的说明注释。
A class for managing and starting requests for Glide. Can use activity, fragment and connectivity lifecycle events to intelligently stop, start, and restart requests. Retrieve either by instantiating a new object, or to take advantage built in Activity and Fragment lifecycle handling, use the static Glide.load methods with your Fragment or Activity.
由此可知,该类就是用于将请求和Activity或Framgent的生命周期做绑定。
类图
将和生命周期相关的类图如下(省略大部分类的变量和方法):
类的简单介绍
- RequestManagerRetriever:该类用于创建RequestManager或在Activity、Fragment中找出已创建的RequestManager,RequestManagerRetriever是一个单例。
- RequestManagerFragment:继承Fragment,不可见,仅用于保存RequestManager,还有一个SupportRequestManagerFragment继承v4包的Fragment,功能类似。
- LifecycleListener:用于监听Activity、Fragment的生命周期事件。
- Lifecycle:用于添加LifecycleListener。
- ActivityFragmentLifecycle:实现Livecycle接口,用于通知Activity、Fragment的生命周期事件。
- RequestTracker:该类用于跟踪、取消和重新启动执行中、已完成和失败的请求。
- ConnectivityMonitor: 监听网络事件的接口,当网络状态发生变化时,影响网络请求状态,继承LifecycleListener。
- DefaultConnectivityMonitor: ConnectivityMonitor的实现类,实现监听网络状态的逻辑。
- RequestManagerConnectivityListener: 实现ConnectivityListener接口,将网络事件传递给RequestTracker。
类的联系
以上对各类有一个简单的了解,接下来将重点讲清楚各类之间的联系。整个生命周期的绑定分为四部分。
- 调用Glide.with(Context),根据传入的Context类型创建RequestManager。Context可以为Activity、Fragment和Application。
- 在传入的参数Activity、或者Fragment中,添加一个不可见的Fragment,监听不可见Fragment的生命周期并将该事件传递给和Fragment一一绑定的RequestManager。
- RequestManager监听到生命事件后,管理图片请求做出响应。
- 监听当网络从无到有时,RequestManager要重新启动图片请求。
代码解读
根据以上内容可直接跟代码可跳过以下内容,印象更加深刻。
第一部分:Glide.with(Context)
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}
`
调用RequestManagerRetriever的get方法如下:
public RequestManager get(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) { //传入的是Fragment
return get((FragmentActivity) context);
} else if (context instanceof Activity) { //传入的是Acitivity
return get((Activity) context);
} else if (context instanceof ContextWrapper) { //传入的是Application
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
以传入参数为Activity类型为例,代码如下:
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager(); //获取FragmentManager
return fragmentGet(activity, fm);
}
}
主要调用fragmentGet方法,代码如下:
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager(); //根据RequestManagerFragment获取RequestManager,一个RequestManagerFragment包含一个RequestManager
if (requestManager == null) { //若RequestManager为空,则新建一个并且设置到RequestManagerFragment中
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
getRequestManagerFragment(fm)函数主要是根据FragmentManager获取Fragment,代码如下:
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); //通过Tag查找
if (current == null) { //若为空,从缓存pendingRequestManagerFragments中查找
current = pendingRequestManagerFragments.get(fm);
if (current == null) { //缓存中也不存在,则新建一个RequestManagerFragment,并且添加到页面中。
current = new RequestManagerFragment();
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
以上就是根据传入的Context类型创建RequestManager的代码部分。
第二部分:监听不可见Fragment的生命周期并传递给RequestManager
添加不可见Fragment的目的,就是因为该Fragment和父类的Activity具有同样的生命周期,无须改动原有Activity的代码,即可实现生命周期的监听。
RequestManagerFragment生命周期相关的代码如下:
public void onStart() {
super.onStart();
lifecycle.onStart(); //执行lifecycle的onStart方法
}
public void onStop() {
super.onStop();
lifecycle.onStop();//执行lifecycle的onStop方法
}
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();//执行lifecycle的onDestroy方法
}
可以看出,Fragment的声明周期的监听都转移到类型是ActivityFragmentLifecycle的变量lifecycle中的对应方法执行。查看ActivityFragmentLifecycle的代码:
void onStart() {
isStarted = true;
//循环set集合lifecycleListeners中所有LifecycleListener,执行对应的onStart
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
//省略onStop()和onDestroy()方法,和onStart()方法类似。
set集合的LifecycleListener是如何添加进去的,看ActivityFragmentLifecycle中的代码:
public void addListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {//如果当前页面已经被destroy,则调用对应的onDestroy
listener.onDestroy();
} else if (isStarted) {//如果当前页面已经开启,则调用对应的onStart
listener.onStart();
} else { //其他情况调用onStop方法
listener.onStop();
}
}
addListener(LifecycleListener listener)方法是接口Lifecycle的方法。RequestManagerFragment提供一个公有方法:
ActivityFragmentLifecycle getLifecycle() {
return lifecycle;
}
回看第一部分创建RequestManager时:
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
RequestManagerFragment中的Lifecycle作为RequestManager的构造函数的参数传递给RequestManager。RequestManager构造函数如下:
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() {
public void run() {
//在主线程中将当前类实现的LifecycleListener添加到lifecycle中。
lifecycle.addListener(RequestManager.this);
}
});
} else {
//在主线程中将当前类实现的LifecycleListener添加到lifecycle中。
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}
由此可见,lifecycle添加的就是RequestManager实现的LifecycleListener接口。
第三部分:RequestManager实现LifecycleListener
接着查看RequestManager实现LifecycleListener的方法:
public void onStart() {
// onStart might not be called because this object may be created after the fragment/activity's onStart method.
resumeRequests();
}
public void onStop() {
pauseRequests();
}
public void onDestroy() {
requestTracker.clearRequests();
}
继续进入resumeRequests()、pauseRequests()和requestTracker.clearRequests()方法可知,都是调用RequestTracker相应的方法,RequestTracker类包含一个集合的Request,该集合包含一个Activity获取一个
Fragment的所以图片请求,将根据RequestManagerFragment的生命周期,统一管理图片请求。
第四部分:监听网络状态并作出相应
RequestManager的构造函数有如下方法:
//省略部分代码...
//监听网络变化的类
ConnectivityMonitor connectivityMonitor = factory.build(context,
new RequestManagerConnectivityListener(requestTracker));
//省略部分代码...
lifecycle.addListener(connectivityMonitor);
//省略部分代码...
以上代码可看出,ConnectivityMonitor也实现了LifecycleListener。继续跟踪代码发现,factory的实例是ConnectivityMonitorFactory,在该工厂中会检查网络权限,同时创建ConnectivityMonitor的实例DefaultConnectivityMonitor。LifecycleListener接口的实现如下:
public void onStart() {
register(); //register()方法为注册广播监听网络变化
}
public void onStop() {
unregister(); //解除监听广播
}
public void onDestroy() {
// Do nothing.
}
广播接收器代码如下:
private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
boolean wasConnected = isConnected;
isConnected = isConnected(context);
if (wasConnected != isConnected) { //当网络状态发生变化时,才调用listener.onConnectivityChanged()方法
listener.onConnectivityChanged(isConnected);
}
}
};
ConnectivityListener 的实例的类型是RequestManager的内部类,代码如下:
private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {
private final RequestTracker requestTracker;
public RequestManagerConnectivityListener(RequestTracker requestTracker) {
this.requestTracker = requestTracker;
}
public void onConnectivityChanged(boolean isConnected) {
if (isConnected) { //如果当前状态是链接状态
requestTracker.restartRequests(); //重新开启图片请求
}
}
}
小结
以上就是Glide实现图片加载和Activity、Fragment生命周期绑定的全部分析。会发现使用了观察者模式和工厂模式进行解耦,其中创建一个不可见的Fragment设置到需要被监控生命周期的Activity、Fragment中,最为精彩。接下来将分析Glide核心设计二:图片缓存。敬请期待。