Volley框架的基本解读

Posted zero_zero_zero_zero

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Volley框架的基本解读相关的知识,希望对你有一定的参考价值。

废话不多说,放上Volley框架的基本解读(三)的链接,我们继续往下看,先来看看网络执行类HttpStack的源码:


/**
 * An HTTP stack abstraction.
 */
public interface HttpStack 
    /**
     * Performs an HTTP request with the given parameters.
     *
     * <p>A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise,
     * and the Content-Type header is set to request.getPostBodyContentType().</p>
     *
     * @param request the request to perform
     * @param additionalHeaders additional headers to be sent together with
     *         @link Request#getHeaders()
     * @return the HTTP response
     * 
     * 真正的网络请求
     */
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
        throws IOException, AuthFailureError;


这是一个接口,里面有一个与Network接口同名,但又不一样的方法。


具体实现是由Volley.newRequestQueue中根据api版本不同,创建的HurlStack或HttpClientStack,前面已经说过两者之间的差别,我们选版本高的来讲,这里值得一提的是,之所以在api9之后不用HttpClient,是因为它有所缺陷,好了,进入正题:


public HurlStack() 
        this(null);
    

继续看:


public HurlStack(UrlRewriter urlRewriter) 
        this(urlRewriter, null);
    

再看:


public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) 
        mUrlRewriter = urlRewriter;
        mSslSocketFactory = sslSocketFactory;
    


UrlRewriter是HurlStack中的一个内部接口,用于URL的重置,我们给的是null,所以不用管它,SSLSocketFactory是https协议用到的类,我们给的也是null,所以也不需要管它,直入主题看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);
        HttpURLConnection connection = openConnection(parsedUrl, request);
        // 添加请求头
        for (String headerName : map.keySet()) 
            connection.addRequestProperty(headerName, map.get(headerName));
        
        setConnectionParametersForRequest(connection, request);
        // Initialize HttpResponse with data from the HttpURLConnection.
        ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
        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.");
        
        StatusLine responseStatus = new BasicStatusLine(protocolVersion,
                connection.getResponseCode(), connection.getResponseMessage());
        BasicHttpResponse response = new BasicHttpResponse(responseStatus);
        response.setEntity(entityFromConnection(connection));
        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;
    

前面都很简单,我们直接看第16行的openConnection方法:


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
        // 如果是https协议
        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) 
            ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
        

        return connection;
    

再看createConnection方法:

protected HttpURLConnection createConnection(URL url) throws IOException 
        return (HttpURLConnection) url.openConnection();
    

很简单吧,仅仅只是封装了(HttpURLConnection) url.openConnection()这一句代码而已,那么上面也就简单了,只是对网络请求进行了一些简单的设置,判断是否是https协议,进行设置。


这里提一点request.getTimeoutMs()获取到的时间其实是DefaultRetryPolicy中mCurrentTimeoutMs,当请求重试时,连接超时的时间会被延长。


随后就是添加请求头,setConnectionParametersForRequest方法用于确定请求方式:


static void setConnectionParametersForRequest(HttpURLConnection connection,
            Request<?> request) throws IOException, AuthFailureError 
        switch (request.getMethod()) 
            case Method.DEPRECATED_GET_OR_POST:
                // This is the deprecated way that needs to be handled for backwards compatibility.
                // If the request's post body is null, then the assumption is that the request is
                // GET.  Otherwise, it is assumed that the request is a POST.
                byte[] postBody = request.getPostBody();
                if (postBody != null) 
                    // Prepare output. There is no need to set Content-Length explicitly,
                    // since this is handled by HttpURLConnection using the size of the prepared
                    // output stream.
                    connection.setDoOutput(true);
                    connection.setRequestMethod("POST");
                    connection.addRequestProperty(HEADER_CONTENT_TYPE,
                            request.getPostBodyContentType());
                    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                    out.write(postBody);
                    out.close();
                
                break;
            case Method.GET:
                // Not necessary to set the request method because connection defaults to GET but
                // being explicit here.
                connection.setRequestMethod("GET");
                break;
            case Method.DELETE:
                connection.setRequestMethod("DELETE");
                break;
            case Method.POST:
                connection.setRequestMethod("POST");
                addBodyIfExists(connection, request);
                break;
            case Method.PUT:
                connection.setRequestMethod("PUT");
                addBodyIfExists(connection, request);
                break;
            default:
                throw new IllegalStateException("Unknown method type.");
        
    

包含GET,DELETE,POST,PUT等等,第一种请无视它,大概的意思是这是过时的,需要处理的向后兼容性,如果该请求的正文无效,则该假设是该请求是GET,否则是POST,老实说我也不知道它想表达什么意思,如果有大神知道还望指教!


之后就是为了统一返回方式,将HttpURLConnection中的属性给予了封装,先是http协议版本,然后封装成状态行,再然后放入BasicHttpResponse中,设置实体,entityFromConnection方法,猜也猜的到是做什么用的:


/**
     * Initializes an @link HttpEntity from the given @link HttpURLConnection.
     * @param connection
     * @return an HttpEntity populated with data from <code>connection</code>.
     * 
     * 将HttpURLConnection换成HttpEntity
     */
    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;
    

很简单,我就不废话了。


最后添加响应头,一个HttpResponse就封装完成了。


到此Volley网络请求这一条线,我们已经全部走完了,希望各位读者能有所收获!


以上是关于Volley框架的基本解读的主要内容,如果未能解决你的问题,请参考以下文章

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley源码解读(上)