Glide核心设计一:皮皮虾,我们走

原文链接:Glide核心设计一:皮皮虾,我们走

引言

皮皮虾,又名虾姑,是淡水中的强者。其头部的两个锤节,可以轻易破坏贝类的外壳,身体上的步足可以保证快速移动。这些优秀的品质,使它被表情包盯上。

Glide,作为Android最优秀的图片加载框架之一,能和Activity和Fragment的生命周期绑定,是区别于其它网络框架的核心特征,也是本文分析的重点。

我们将此特征和皮皮虾表情包做一个类比:
皮皮虾和Glide类比
图片网络请求紧跟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的生命周期做绑定。

类图

将和生命周期相关的类图如下(省略大部分类的变量和方法):
声明周期绑定类图

类的简单介绍

  1. RequestManagerRetriever:该类用于创建RequestManager或在Activity、Fragment中找出已创建的RequestManager,RequestManagerRetriever是一个单例。
  2. RequestManagerFragment:继承Fragment,不可见,仅用于保存RequestManager,还有一个SupportRequestManagerFragment继承v4包的Fragment,功能类似。
  3. LifecycleListener:用于监听Activity、Fragment的生命周期事件。
  4. Lifecycle:用于添加LifecycleListener。
  5. ActivityFragmentLifecycle:实现Livecycle接口,用于通知Activity、Fragment的生命周期事件。
  6. RequestTracker:该类用于跟踪、取消和重新启动执行中、已完成和失败的请求。
  7. ConnectivityMonitor: 监听网络事件的接口,当网络状态发生变化时,影响网络请求状态,继承LifecycleListener。
  8. DefaultConnectivityMonitor: ConnectivityMonitor的实现类,实现监听网络状态的逻辑。
  9. RequestManagerConnectivityListener: 实现ConnectivityListener接口,将网络事件传递给RequestTracker。

类的联系

以上对各类有一个简单的了解,接下来将重点讲清楚各类之间的联系。整个生命周期的绑定分为四部分。

  1. 调用Glide.with(Context),根据传入的Context类型创建RequestManager。Context可以为Activity、Fragment和Application。
  2. 在传入的参数Activity、或者Fragment中,添加一个不可见的Fragment,监听不可见Fragment的生命周期并将该事件传递给和Fragment一一绑定的RequestManager。
  3. RequestManager监听到生命事件后,管理图片请求做出响应。
  4. 监听当网络从无到有时,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生命周期相关的代码如下:

@Override
   public void onStart() {
       super.onStart();
       lifecycle.onStart(); //执行lifecycle的onStart方法
   }

   @Override
   public void onStop() {
       super.onStop();
       lifecycle.onStop();//执行lifecycle的onStop方法
   }

   @Override
   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中的代码:

@Override
    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() {
               @Override
               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的方法:

@Override
   public void onStart() {
       // onStart might not be called because this object may be created after the fragment/activity's onStart method.
       resumeRequests();
   }

   @Override
   public void onStop() {
       pauseRequests();
   }

   @Override
   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接口的实现如下:

@Override
   public void onStart() {
       register(); //register()方法为注册广播监听网络变化
   }

   @Override
   public void onStop() {
       unregister(); //解除监听广播
   }

   @Override
   public void onDestroy() {
       // Do nothing.
   }

广播接收器代码如下:

private final BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
      @Override
      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;
       }

       @Override
       public void onConnectivityChanged(boolean isConnected) {
           if (isConnected) { //如果当前状态是链接状态
               requestTracker.restartRequests(); //重新开启图片请求
           }
       }
   }

小结

以上就是Glide实现图片加载和Activity、Fragment生命周期绑定的全部分析。会发现使用了观察者模式和工厂模式进行解耦,其中创建一个不可见的Fragment设置到需要被监控生命周期的Activity、Fragment中,最为精彩。接下来将分析Glide核心设计二:图片缓存。敬请期待。