Volley的框架解读一(Http的封装)

先瞄瞄UML类图

httpstack

 

 

在Volley中真正的网络请求是由HttpStack定义的,这是一个接口,它唯一的一个方法就是执行网路请求获取响应。而HttpClientStack和HurlStack是该接口的实现类,对应不同的网络请求的底层实现,HttpClientStack是基于HttpClient的,HurlStack是基于HttpURLConnection的。

先看看这个父接口(HttpStack)

源码解读绝招一:看父类,接口,这样你才知道这个类是干啥的,应该有什么行为
/**
 * Volley中真正去执行联网的类,返回的信息封装成HttpResponse
 */
public interface HttpStack {


    /**
     *  真正去执行联网的方法
     */
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
        throws IOException, AuthFailureError;

}

Volley本来是支持HttpURLConnection,还有HttpClient的,当然处于现在这个年代,HttpClient被废弃了,所以只看HttpURLConnection的封装

另外说一点Volley中的Request,从字面理解上是请求,但是其实不是一个真正的网络请求,个人理解为是对真正的网络请求的各个属性的描述。

HttpStack是真正的网络请求,Request则是封装了超时时间、请求方式、参数、url等网络请求所必须的参数。通过变换不同的属性参数(最基本的如请求方式GET POST),可以获取不同的网络请求。

OK,现在在说下我对于HttpClientStack和HurlStack的理解,二者的工作思路是这样的:

1. 首先从Volley的Request内获取各个属性、如超时间、请求方式、参数和url

2.创建网络请求,HttpClientStack是创建HttpClient ,HurlStack是创建HttpURLConnection

3.对网络请求设置各个属性参数

4.定义执行网路请求的方法,并获取响应,将响应返回出去

上面说的是思路,现在看一下源码细节是怎么写的,一些得从performRequest开始

源码细节performRequest
@Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        String url = request.getUrl();
        HashMap<String, String> map = new HashMap<String, String>();
        map.putAll(request.getHeaders());
        map.putAll(additionalHeaders);
        if (mUrlRewriter != null) {
            String rewritten = mUrlRewriter.rewriteUrl(url);
            if (rewritten == null) {
                throw new IOException("URL blocked by rewriter: " + url);
            }
            url = rewritten;
        }
        URL parsedUrl = new URL(url);
        //1.得到一个HttpURLConnection
        HttpURLConnection connection = openConnection(parsedUrl, request);
        //2.设置响应头
        for (String headerName : map.keySet()) {
            connection.addRequestProperty(headerName, map.get(headerName));
        }
        //3.设置请求方式
        setConnectionParametersForRequest(connection, request);
        //4.响应的协议版本
        ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
        //5.获取状态码
        int responseCode = connection.getResponseCode();
        if (responseCode == -1) {
            // -1 is returned by getResponseCode() if the response code could not be retrieved.
            // Signal to the caller that something was wrong with the connection.
            throw new IOException("Could not retrieve response code from HttpUrlConnection.");
        }
        //6.根据链接获取响应的状态码响应信息
        StatusLine responseStatus = new BasicStatusLine(protocolVersion,
                connection.getResponseCode(), connection.getResponseMessage());
        //创建响应
        BasicHttpResponse response = new BasicHttpResponse(responseStatus);
        //给响应设置响应体,响应体来自于链接
        response.setEntity(entityFromConnection(connection));
        //将得到的头信息赋值给实体类(BasicHttpResponse)
        for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
            if (header.getKey() != null) {
                Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
                response.addHeader(h);
            }
        }
        return response;
    }

看传入参数Request,里面有设置了很多http的属性,如超时,是否缓存,还有一个参数设置头信息

再看看其中几个重要方法

  • openConnection
  • setConnectionParametersForRequest 设置请求方式
  • entityFromConnection
openConnection封装细节
   /**
     * 设置HttpURLConnection 一些参数以及支持https
     * @param url
     * @return an open connection
     * @throws IOException
     */
    private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
        HttpURLConnection connection = createConnection(url);

        int timeoutMs = request.getTimeoutMs();
        connection.setConnectTimeout(timeoutMs);
        connection.setReadTimeout(timeoutMs);
        connection.setUseCaches(false);
        connection.setDoInput(true);

        // use caller-provided custom SslSocketFactory, if any, for HTTPS
        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
            ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
        }

        return connection;
    }

没啥好说的就是创建了HttpURLConnection,设置一些属性

entityFromConnection封装细节
  /**
     * 将connection得到的信息封装成实体(BasicHttpEntity)返回
     * @param connection
     * @return
     */
    private static HttpEntity entityFromConnection(HttpURLConnection connection) {
        BasicHttpEntity entity = new BasicHttpEntity();
        InputStream inputStream;
        try {
            inputStream = connection.getInputStream();
        } catch (IOException ioe) {
            inputStream = connection.getErrorStream();
        }
        entity.setContent(inputStream);
        entity.setContentLength(connection.getContentLength());
        entity.setContentEncoding(connection.getContentEncoding());
        entity.setContentType(connection.getContentType());
        return entity;
    }

这里就是从HttpURLConnection获取接口信息,封装成HttpEntity,返回给调用者BasicNetWork

Volley的真正的网络请求就是这些了,注意这里是定义网络请求和网络请求的方法,但是调用执行网络请求其实是在NetWork接口及其实现类BasicNetwork内。

如果对于HttpURLConnection 不太了解,或者忘记的差不对了可以看看我前面文章

Volley的框架解读准备一HttpURLConnection

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值