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

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

@[Volley, 网络请求, HttpStack]

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

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):设置head

private 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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值