Volley源码解析<六> HttpStack网络请求

来源:互联网 发布:反马赛克软件torch 编辑:程序博客网 时间:2024/05/20 17:26

Volley源码解析<六> HttpStack网络请求

@[Volley, 网络请求, HttpStack]

声明:转载请注明出处,知识有限,如有错误,请多多交流指正!

  • Volley源码解析六 HttpStack网络请求
      • HttpStack网络请求结构
      • HttpStack接口说明
      • HurlStack请求
        • MethodDEPRECATED_GET_OR_POST这个请求是什么
        • MethodDEPRECATED_GET_OR_POST如果有人知道这是什么请求麻烦请告之
        • 为什么connectiongetResponseCode401就会抛出IOExceptionvolley 401错误处理
      • HttpClientStack请求

HttpStack网络请求结构

HttpStack网络请求

HttpStack接口说明

HttpStack处理 Http 请求,返回请求结果,只有一个抽象方法,子类实现

    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)throws IOException, AuthFailureError;
  • request:请求数据
  • additionalHeaders:添加额外的请求 Headers
  • HttpResponse:返回结果

HurlStack请求

主要内部主要封装实现HttpURLConnection

1. 构造方法

public HurlStack()public HurlStack(UrlRewriter urlRewriter)public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory)

其中

urlRewriter:对url进行重写,重写的好处使url更加的保密,安全
sslSocketFactory:用于Https请求

Volley.java调用public HurlStack(),也就urlRewriter和sslSocketFactory都设置为Null,也就是不设置

2. 主要调用performRequest方法发起请求

代码流程
- 添加head:请求head+额外的head
- 设置是否对url进行重写
- 通过openConnection建立连接
- 设置请求的相关属性
- 获取响应码和响应信息处理
- 处理数据和head,返回数据

 @Override    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)            throws IOException, AuthFailureError {        String url = request.getUrl();        //添加head:请求head+额外的head        HashMap<String, String> map = new HashMap<String, String>();        map.putAll(request.getHeaders());        map.putAll(additionalHeaders);        //目前没有使用到,对url进行重写,重写的好处使url更加的保密,安全        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);        //获取响应中的实体        if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) {            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;    }

private HttpURLConnection openConnection(URL url, Request

     // use caller-provided custom SslSocketFactory, if any, for HTTPS        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {            //设置自定义SSL Https连接            ((HttpsURLConnection) connection).setSSLSocketFactory(mSslSocketFactory);        }

默认请求连接和读取的时间是2.5s,通过代码追踪在DefaultRetryPolicy

    public static final int DEFAULT_TIMEOUT_MS = 2500;

static void setConnectionParametersForRequest(HttpURLConnection connection,Request

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:            ...省略...        }    }

Method.DEPRECATED_GET_OR_POST这个请求是什么?

按照注释所说:这是一个过时的的方法为了向后兼容。如果请求的body为空,那么请求就是GET请求;否则这个请求就是POST请求,那么假如postBody为空,没有处理,这是不是一个bug?不是bug,因为HttpURLConnection 的默认值是GET,可以不用设置,所以没有else;

Method.DEPRECATED_GET_OR_POST:如果有人知道这是什么请求,麻烦请告之!!!

为什么connection.getResponseCode(401)就会抛出IOException?(volley 401错误处理)

volley 401 错误产生原因和解决方案 :
http://blog.csdn.net/kufeiyun/article/details/44646145
http://stackoverflow.com/questions/30476584/android-volley-strange-error-with-http-code-401-java-io-ioexception-no-authe

结果数据封装

private static HttpEntity entityFromConnection(HttpURLConnection connection)
将获取到的数据封装到HttpEntity中,在封装到BasicHttpResponse,返回数据

网络请求携带请求数据

private static void addBodyIfExists(HttpURLConnection connection, Request

HttpClientStack请求

主要内部主要封装实现HttpClient

1. 构造方法

public HttpClientStack(HttpClient client)

其中

client:Volley.java调用了 stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));传入的是AndroidHttpClient
AndroidHttpClient是什么?可以阅读HTTP服务(7):AndroidHttpClient博客

2. 网络请求调用newRequestQueue方法

    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError {        //创建请求        HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders);        //添加head        addHeaders(httpRequest, additionalHeaders);        addHeaders(httpRequest, request.getHeaders());        //准备请求回调        onPrepareRequest(httpRequest);        HttpParams httpParams = httpRequest.getParams();        int timeoutMs = request.getTimeoutMs();        // TODO: Reevaluate this connection timeout based on more wide-scale        // data collection and possibly different for wifi vs. 3G.        // 设置连接超时时间5S        HttpConnectionParams.setConnectionTimeout(httpParams, 5000);        // 设置请求超时,默认设置2.5s        HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);        //  执行        return mClient.execute(httpRequest);    }

HurlStack不同的是,HttpClientStack设置连接超时时间是5S,而HurlStack是2.5s

3. 其他方法

private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers):设置headprivate static List<NameValuePair> getPostParameterPairs(Map<String, String> postParams):将Map数据转成List<NameValuePair> static HttpUriRequest createHttpRequest(Request<?> request, Map<String, String> additionalHeaders):创建请求方式private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest, Request<?> request):设置body数据
0 0