您的位置:首页 > 理论基础 > 计算机网络

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

2017-09-17 16:31 351 查看
先看UML图





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

在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具体执行了网络请求,它有这么几个作用:

执行HttpStack网络请求,获取响应。

请求网络,如果请求失败还需要进行请求重试策略

解析响应,组装成可以被volley传递的NetworkResponse

在解析响应实体的时候,使用字节数组缓冲池技术

主要方法也就是: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);
}
}
}
}


当然也没什么难得地方,代码注释也写的很清楚。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: