Volley的框架解读二(Http访问及处理)

先看UML图

 

baicnetwork

源码解读绝招二:把握类的主要流程,大体看一下用到的类,看看方法,猜一下用法,别去抓细节。

在volley中执行网络请求的接口是Network,其实现类是BasicNetwork。

需要注意的是,将Network与HttpStack、HttpClientStack 、HurlStack进行区别。HttpStack是定义网络请求的,是使用HttpClient或者HttpURLConnection来连接网络。Network则是使用HttpStack来执行网络请求,Network是使用者。

不清楚HttpStack可以看我上一篇文章

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

Network接口内定义了一个唯一的方法public NetworkResponse performRequest(Request<?> request) 其作用就是执行网络请求,并获取返回值。

/**
 *
 * 调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
 * 代表网络的接口,处理网络请求。 唯一的方法,用于执行特定请求
 */
public interface Network {

/**
 * @param request 执行网络请求,获取一个从网络后返回的响应 ,BasicNetwork是该接口的实现类 
 * @return NetworkResponse是响应数据,该数据是根据从缓存获得或从网络中获取的响应数据封装起来的 
 * @throws VolleyError
 */
public NetworkResponse performRequest(Request<?> request) throws VolleyError;
}

Network是一个接口,volley中该接口的默认实现类是BasicNetwork。

BasicNetwork具体执行了网络请求,它有这么几个作用:

  1. 执行HttpStack网络请求,获取响应。
  2. 请求网络,如果请求失败还需要进行请求重试策略
  3. 解析响应,组装成可以被volley传递的NetworkResponse
  4. 在解析响应实体的时候,使用字节数组缓冲池技术

 

主要方法也就是:performRequest(),在volley中也就是使用HttpStack获取响应内容,然后根据响应码来做一些重试策略,缓存策略。

其实volley源码中,可以看到每个类基本做到了就是一个作用(单一职责),同时也通过组合的形式,添加一些新的职责,比如BasicNetwork
基本就是处理了,不同响应码有不同的处理

 @Override
    public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();
        //这里使用while(true)的含义是:保证请求重试策略的执行。
        //如果网络正常返回结果 那么直接return
        //如果需要进行请求重试,就用到这里了,保证了可以进行请求重试
        while (true) {
            //系统的网络请求的响应
            HttpResponse httpResponse = null;
            //存放响应实体的字节数组
            byte[] responseContents = null;
            //存储响应头信息的map
            Map<String, String> responseHeaders = new HashMap<String, String>();
            try {
                // Gather headers.
                Map<String, String> headers = new HashMap<String, String>();
                //从request中获取一些头的信息,新鲜度验证的tag和缓存的响应的响应时间
                addCacheHeaders(headers, request.getCacheEntry());
                //执行请求,获得相应
                httpResponse = mHttpStack.performRequest(request, headers);
                //获取响应的状态行
                StatusLine statusLine = httpResponse.getStatusLine();
                //获取状态码
                int statusCode = statusLine.getStatusCode();
                //将响应的头信息转为map存储
                responseHeaders = convertHeaders(httpResponse.getAllHeaders());
                // Handle cache validation.  返回的状态码是304  表示可以使用缓存数据
                if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                            request.getCacheEntry().data, responseHeaders, true);
                }
                // Some responses such as 204s do not have content.  We must check.204(无内容)服务器成功处理了请求,但没有返回任何内容
                if (httpResponse.getEntity() != null) {
                    //响应实体不为空,使用的是响应实体的数据,获取响应的实体  转为字节数组
                    //这里有可能抛出IO异常,当出现异常的时候需要再下面捕获异常并进行处理,主要是完成创建可被传递的NetworkResponse
                    responseContents = entityToBytes(httpResponse.getEntity());
                } else {
                    // Add 0 byte response as a way of honestly representing a
                    // no-content request.
                    responseContents = new byte[0];
                }

                // if the request is slow, log it.
                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                logSlowRequests(requestLifetime, request, responseContents, statusLine);

                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }
                //根据httpResponse的信息,组装成可以被volley传递的networkresponse
                //此时while循环结束
                return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
                //如果发生超时,认证失败等错误,进行重试操作,直到成功、抛出异常(不满足重试策略等)结束
            } catch (SocketTimeoutException e) {
                //当出现异常的时候,尝试进行请求重试
                attemptRetryOnException("socket", request, new TimeoutError());
            } catch (ConnectTimeoutException e) {
                //当出现连接异常的时候,尝试进行请求重试
                attemptRetryOnException("connection", request, new TimeoutError());
            } catch (MalformedURLException e) {
                //url不正常异常
                throw new RuntimeException("Bad URL " + request.getUrl(), e);
            } catch (IOException e) {
                //当出现IO异常时,在try内读取数据体时,如果出现IO异常,那么捕获异常,继续完成创建NetworkResponse的过程
                int statusCode = 0;
                NetworkResponse networkResponse = null;
                //如果响应不为空
                if (httpResponse != null) {
                    //获取返回的状态码
                    statusCode = httpResponse.getStatusLine().getStatusCode();
                } else {
                    //响应为空就表明 网络连接错误
                    throw new NoConnectionError(e);
                }
                VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                if (responseContents != null) {
                    //根据状态码、响应的实体数、响应头信息创建可被传递的响应
                    networkResponse = new NetworkResponse(statusCode, responseContents,
                            responseHeaders, false);
                    //如果状态码是授权未通过
                    if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
                            statusCode == HttpStatus.SC_FORBIDDEN) {
                        //请求重试策略
                        attemptRetryOnException("auth",
                                request, new AuthFailureError(networkResponse));
                    } else {
                        // TODO: Only throw ServerError for 5xx status codes.
                        throw new ServerError(networkResponse);
                    }
                } else {
                    throw new NetworkError(networkResponse);
                }
            }
        }
    }

当然也没什么难得地方,代码注释也写的很清楚。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值