Volley源码解析(一)

之前写了几篇关于okhttp源码解析的文章,所以就趁热看了下volley的源码实现,然后就打算写几篇关于volley源码分析的文章 ,虽然网上关于它的源码解析的文章也不少,但是自己写了总有些许收获。这也算是写博客或者分析源码带来的好处吧。本系列的博客可能会与okhttp进行对比,所以建议各位码友们移步此处大致看下(当然有不对的地方也欢迎批评指正)

其实,各个网络请求框架无非就是对基本的http的get和post等方法的封装,让客户短可以很方便的调用而已。基本核心功能就是以某种方式组织或者封装请求参数:请求头,请求体,然后在通过网络访问的库(Socket,HttpClient,HttpURLConnection等)发起网络请求,然后返回服务器返回的结果的过程:
这里写图片描述

从代码设计角度来看请求和响应都是上层接口,而各个版本的框架则是接口的具体实现,比如代码:

interface Request {}
class VolleyRequest implements Request{}
class OkhttpRequest implements Request{}
class OtherReqeust implements Request{}

interface Response{}
class VolleyResoponse implements Response{}
class OkhttpResonse implements Response{}
class OtherResponse implements Response{}

而网络请求框架对request请求参数的组织和封装,以及对响应的处理,每个网络请求框架都有自己的处理方式。当然各个框架的处理其内部细节是不一样的,比如:volley支持请求优先级,而okhttp则不支持。volley通过HttpClient或者HttpURLConnection/HttpClient,而okhtpp则通过Socket来进行网络请求和响应的处理。

那么上图就可以演化成如下的图:
这里写图片描述

Volley概述
那么Volley中是具体是怎么处理的呢?观察下其源码,发现可以用如下图来体现volley对Request和Response的组织方式:

这里写图片描述

也就是说Volley对Request和Response的封装提供了如下代码:

abstract class Request<T>
class StringRequest<String> extends Request<String>
class ImageRequest<Bitmap> extends Request<Bitmap>
abstract class JsonRequest<T> extends Request<T>

class JsonObjectRequest<JSONObject> extends JsonRequest<JSONObject>

class JsonArrayRequest<JSONArray> extends JsonRequest<JSONArray>

然后Volley通过HttpURLConnection/HttpClient发起请求,内部会先将服务器返回的数据组织成HttpResponse,然后转换成NetworkResponse,最终交给Response<>通过接口Response.Listener接口方法传参的方式讲对应的数据对象:String,Bitmap,JsonObject等交给客户端。这个过程在代码上有点绕,下面会仔细说明。

Volley发起链接:

在volley中提供了HttpStack接口作为发起链接的接口,该接口提供了performRequest方法,该方法执行完毕后返回一个org.apache.http.HttpResponse对象,volley提供了几个该接口的实现类:

 interface HttpStack{}
 class HttpClientStack implements HttpStack{}
 class BaseHttpStack implements HttpStack {}
 class HurlStack extends BaseHttpStack {}

鉴于HttpStack和HttpClientStack已经被volley标志为废弃,所以我们首先来分析分析BaseHttpStack及其子类HurlStack.看看他们都做了什么:

BaseStack是一个抽象类,并且提供了抽象方法,这个方法也是废弃了HttpStack的接口之后performRequest方法的替代品:

    /**
     *注意这个方法返回的HttpResponse是volley自身提供的一个类,而不是org.apache.http.HttpResponse
     */
    public abstract HttpResponse executeRequest(
            Request<?> request, Map<String, String> additionalHeaders);

之所以废弃HttpStack,估计是因为volley打算废弃org.apache.包的引入吧,这样可以提高实现的灵活性,如果客户端需要用org.apache.http.HttpResponse 的还可以自己引入。至于executeRequest的作用无非就是发起链接,然后将服务器的数据组装成HttpResponse对象呗。
那么从HttpStack代码组织的角度来说,Volley的整个http请求可以用如下来表示:
这里写图片描述

从上图看,Volley不仅仅可以使用自己的HttpStack来完成网络请求,客户端也可以实现自己的HttpStack来完成http的请求,比较灵活(鉴于HttpStack标志为废气,此处建议客户端通过继承BastHttpStack来实现自己的HttpStack)

volley默认的如果android版本号大于等于9,内部就是用的HurlStack:


 public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
      BasicNetwork network;
      if (stack == null) {//客户端自定义HttpStack
          if (Build.VERSION.SDK_INT >= 9) {
             network = new BasicNetwork(new HurlStack());
          } else {
              //省略部分代码
            network = new BasicNetwork(new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
          }
      } else {//用客户端自己的stack实现
          network = new BasicNetwork(stack);
      }

      return newRequestQueue(context, network);
    }

上面的代码表明如下几个方面:
1、如果客户端自定义了HttpStack或者BaseStack,则使用自己的网络请求工具发起访问,这样提高了volley使用的灵活性
2、如果没有自定义HttpStack或者BaseStack,那么版本号大于等于9的就使用HurlStack,反之则使用HttpClientStack
3、注意上面的代码中创建了BasicNetwork,这个后面会提到它。

所以现在来分析分析HurlStack这个类。
HurlStack简单分析
下面我们来看看BaseHttpStack的子类HurlStack的具体实现, 看看HurlStack关于executeRequest的实现方案:

public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders) {
            String url = request.getUrl();
            HashMap<String, String> map = new HashMap<>();
            //获取请求头
            map.putAll(request.getHeaders());
            map.putAll(additionalHeaders);

            //省略部分代码

            URL parsedUrl = new URL(url);
            //打开一个HttpURLConnection
            HttpURLConnection connection = openConnection(parsedUrl, request);
            //设置请求头信息
            for (String headerName : map.keySet()) {
                connection.addRequestProperty(headerName, map.get(headerName));
            }
            //设置请求参数
            setConnectionParametersForRequest(connection, request);
           //省略部分代码
            if (!hasResponseBody(request.getMethod(), responseCode)) {
                return new HttpResponse(。。。。);
            }

            return new HttpResponse(。。。。);
        }

到此前文说的HttpURLConnection终于露面了。executeRequest执行完之后就返回了HttpResponse,前面图三表明HttpResponse会先转换成NetworkResponse,那么这一步在哪儿实现的呢?在回答这个问题之前,先回答一个问题:volley什么时候发起网络请求的呢?这个问题回答了,上一个问题也就迎刃而解。

Volley执行HttpStack executeRequest的类

还记得前文出现了BasicNetwork么?其初始化的时候(看SDK大于9的情况)传入了HurlStack:

  if (Build.VERSION.SDK_INT >= 9) {
       network = new BasicNetwork(new HurlStack());
  }

BasicNetwork实现了NetWork接口的performRequest方法,该方法就是返回了一个NetworkResponse对象,剥离了与本文无关代码之后,可以简单如下列所示:

public NetworkResponse performRequest(Request<?> request) {
        while (true) {//一个循环
            HttpResponse httpResponse = null;
            //此处省略部分代码

            //执行HttpStack的executeRequest
   httpResponse = mBaseHttpStack.executeRequest(request, headers);

           //此处省略部分代码

            return new NetworkResponse(。。。);

        }//end while
    }

也就是说该类的主要工作就是调用HttpStack的executeRequest方法,然后将HttpResponse辗转处理后返回了NetWorkResponse,其具体细节限于篇幅暂且本文暂且不讲。

写到此处,Volley生成NetWorkResponse的的流程已经讲解完毕,那最后一步生成 Response对象又是交给谁来完成的呢?或者说BasicNetWork这个对象performRequest方法在volley中是什么时候调用到呢?这些问题将在博主的下一篇博客中讲解,敬请期待,欢迎批评指正

猜你喜欢

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