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

原文连接:Glide核心设计一:皮皮虾,咱们走java

引言

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

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

咱们将此特征和皮皮虾表情包作一个类比:
github

皮皮虾和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的生命周期作绑定。app

类图

将和生命周期相关的类图以下(省略大部分类的变量和方法):
框架

声明周期绑定类图

类的简单介绍

  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。

类的联系

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

  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核心设计二:图片缓存。敬请期待。

相关文章
相关标签/搜索