Volley,Okhttp,Retrofit源码研究心得大总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chunqiuwei/article/details/83997118

Volley源码解析系列
Okhttp源码解析系列
Retrofit源码解析系列

注:阅读本篇博文之前建议阅读上面几个系列的博文,算是本篇文章的理论储备。

以前在业余的时候阅读过Volley,Okhttp,Retrofit的源码,本篇就对他们做一个大总结和巩固。

1、框架涉及到的设计模式
工厂模式:这个模式很简单,与其说是一个模式,不如说它是一个变成习惯。该模式的直观作用之一就是减少重复代码,方便复用。虽然该模式很简单,但是各大框架里面都有这个模式的影子,比如Gson,Okhttp,Retrofit,Glide等等,可谓使用广泛。所以在平时开发中可以考虑使用此模式。

构建者模式:该模式简单实用,可以说是一些公共框架的最爱,该模式主要是用来一步步构建所需对象的组件对象。当然该模式在可以用来优化方法参数过长的方法及其重载方法。

单例模式:如果说别的模式很陌生的话,那么这个模式肯定不回陌生,不论在面试还是开发中都会遇到此模式。比如我们使用的Glide,EventBus等等一般都是用他们的单利对象。当然使用单利模式要留心一下内存泄露问题。

当然在框架中还可以看到其他常用的模式,比如适配器模式和代理模式。在此不在赘述。

2、框架的必要性
其实框架的产生主要是为了解决特定的问题,比如图片框架用来处理加载图片、网络框架用来处理网络请求。这是框架层面的单一职责的表现。框架共同的特点就是代码复用,避免我们重复制造轮子。
如果没有网络框架或者其他包含异步任务的框架,那么我们可能就要按照下图的思路编造自己的轮子了(图1:)
在这里插入图片描述

如上图,如果你想重复造一个网络框架或者图片框架的轮子,可能就逃不开上图的思路,以网络框架为例:
1、构建一个网络请求任务(build tasks)
2、将任务添加到线程池中(enqueue)
3、线程池现成执行任务(execute tasks)
4、将异步任务执行的结果通过回调返回给客户端( callback(result))

当然,可能你的异步任务很简单;但是设计一个异步任务的工具基本上也就是下面的三种思路:
1、单个线程完成一个简单的任务:直接new 一个thread 对象,在其run方法里面执行
2、多个线程+队列:
将任务添加到队列中,然后开启一个或者多个线程从任务队列中获取任务并执行,比如Volley就是此种设计
3、线程池的方式:
线程池的使用方式很简单,因为Java封装了线程池供我们使用,核心代码如下所示:

ExecutorService servcie = new ThreadPollExecutor(0,3,TimeUnit.SECONDS,new YourQueue<Runnablle>(),YouThreadFactory());
//执行异步任务
servcie.enqueue(youTaskRunnable)

当然也会有其他不同的实现方式,水平有限不在列举。

带着上面的理论,开始下面的说明。

3、网络请求是什么?
这个问题有点故弄玄虚,网络请求在本篇的观点是客户端发起请求(Request),然后服务器返回数据(Response)的过程如图所示(图2)。
在这里插入图片描述

对该句话进行抽象的话可以剥离出三个接口:Request接口负责构建网络请求对象,Response接口负责封装网络返回的数据。而执行网络请求到数据返回的可以抽象出另外一个接口Call,三者简单的代码如下所示:

interface Request{
}
interface Response{
   byte[] data;//服务器数据
}

interface Call{
  Response execute(Reqeust request);
}

上面的图片和代码从抽象层面对此网络请求做了简单的设计,在Java中发起网络请求的基本手段有Socket,HttpClient,HttpUrlConnection…在此基础上还有一些各自封装的框架,所以上面的图如果考虑实现细节的话,就可以演变成下面的这幅图(图3):
在这里插入图片描述

不同的框架对上图有不同的封装和实现, 如果从设计模式的角度来看,其实就是一个策略模式,在执行网络请求的时候不同的框架都有自己的处理逻辑,但是最终返回的数据肯定是一样的,比如你用Volley 请求一个美女图片的信息,换成Okhttp发起同样的访问时返回的不可能是动物的图片。
所以用策略模式来拓展图3的话,就可以演变成下面这幅图(图4):
在这里插入图片描述

4、各个框架的对图1,图4的演变

上面说过不同的网络框架对网络请求的封装从整体上来看是策略模式的体现,那么Volley对图3或者说图1做了怎样的转变呢?看下图(图5):
在这里插入图片描述

从上图(图5)看,volley采用的访问网络的策略是使用HttpClient和HttpUrlConnection来进行网络请求,同时提供了不同的Request和Response实现。比如你想返回一个String,那么就用StringRequest;需要返回Json的话就用JsonRequest。Volley内部帮我们自动调用parseNetwordResponse方法,该方法是Request基类的抽象方法:

protected abstract Response<T> parseNetwordResponse(NetworkResonse res);

然后上图中不同的Request对象实现parseNetwordResponse方法,这其实就是模板模式的简单应用。

根据图1的理论,来简单看下Volley是怎么处理异步请求的。在volley中是没有用到线程池的,其内部也就默认初始化了四个NetworkDispatcher对象(thread)。然后将所有的请求添加到BlockingQueue中。工作时每个NetworkDispatcher不断从队列中获取Request并执行的过程:

public void start() {
        for (int i = 0; i < mDispatchers.length; i++) {//默认大小是4     
            NetworkDispatcher networkDispatcher =
            new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
   }

而NetworkDispathcer的run方法大致如下所示:


    public void run() {
        while (true) {//一个while循环
            Request<?> request = mQueue.take();

            NetworkResponse networkResponse = mNetwork.performRequest(request);

            //在工作线程将数据转换成Response对象
            Response<?> response =request.parseNetworkResponse(networkResponse);

            //callback返回数据
            mDelivery.postResponse(request, response);
        }
    }

说完了Volley,那么在来看看Okhttp对图3做了怎样的演化。Okhttp是以一些列拦截器为核心来执行网络请求的,该框架对图3的演化可以用下图(图6)来表示:
在这里插入图片描述
关于Okhttp拦截其的工作细节,可以点此了解更多
从图5和图6来看,同样是执行网络请求,二者的实现差异还是巨大的。都是执行网络请求,不同的实现有不同的策略。算是策略模式的一种体现吧。

最后在简单看一下Okhttp是怎么执行同步和异步请求的,为了达到这一目的,Okhttp设计了一个接口:

interface Call {
   Response execute() throws IOException;
 //Callback 为异步请求回调
  void enqueue(Callback responseCallback);
}

Okhttp的通过和异步请求代码如下:

Call call = new OkhttClient().newCall(request);
Response response = call.execute();
//异步请求
Response response = okhttpClient.newCall(request).enqueue(callback);

其实在Java中任何异步任务的处理特别是牵扯到线程池的时候,基本都是交给Thread或者Runnable来完成的。Okhttp也不例外。Okhttp的同步请求直接调用RealCall,而异步请求则交给了AsyncCall(extends NamedRunnable)。具体执行异步请求的地方,可以参考Okhttp的Dispatcher,或者点击此处了解更多

猜你喜欢

转载自blog.csdn.net/chunqiuwei/article/details/83997118