Android中的volley_4_执行网络请求的接口Network及其实现类BasicNetwork
来源:互联网 发布:淘宝开店需要押金吗 编辑:程序博客网 时间:2024/06/05 20:54
demo下载:http://download.csdn.net/detail/vvzhouruifeng/8747599
在volley中执行网络请求的接口是Network,其实现类是BasicNetwork。
需要注意的是,将Network与HttpStack、HttpClientStack 、HurlStack进行区别。HttpStack是定义网络请求的,是使用HttpClient或者HttpURLConnection来连接网络。Network则是使用HttpStack来执行网络请求。
Network接口内定义了一个唯一的方法public NetworkResponse performRequest(Request<?> request) 其作用就是执行网络请求,并获取返回值。
/** * An interface for performing requests. * 调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。 * * 代表网络的接口,处理网络请求。 唯一的方法,用于执行特定请求 */public interface Network {/** * Performs the specified request. 执行网络请求,获取一个从网络后返回的响应 ,BasicNetwork是该接口的实现类 * * @param request * Request to process * @return A {@link NetworkResponse} with data and caching metadata; will * never be null NetworkResponse是响应数据,该数据是根据从缓存获得或从网络中获取的响应数据封装起来的 * @throws VolleyError * on errors */public NetworkResponse performRequest(Request<?> request)throws VolleyError;}
Network是一个接口,volley中该接口的默认实现类是BasicNetwork。
BasicNetwork具体执行了网络请求,它有这么几个作用:
1.在构造的时候需要确定使用的网络请求方式,需要HttpStack的实现类,HttpClientStack 或者HurlStack
2.执行HttpStack网络请求,获取响应。
3.请求网络,如果请求失败还需要进行请求重试策略
4.解析响应,组装成可以被volley传递的NetworkResponse
5.在解析响应实体的时候,使用字节数组缓冲池技术
public class BasicNetwork implements Network { protected static final boolean DEBUG = VolleyLog.DEBUG; private static int SLOW_REQUEST_THRESHOLD_MS = 3000; //默认的byte[]缓冲池的大小 private static int DEFAULT_POOL_SIZE = 4096; //具体的执行网络请求的实例,这里使用的是接口,可以用接口的实现类HttpClientStack HurlStack的实例 protected final HttpStack mHttpStack; //因为大量用到byte[],考虑节省内存问题,创建了一个byte数组缓冲池 protected final ByteArrayPool mPool; /** * @param httpStack HTTP stack to be used * 使用默认大小的字节数组缓冲池 * */ public BasicNetwork(HttpStack httpStack) { // If a pool isn't passed in, then build a small default pool that will give us a lot of // benefit and not use too much memory. this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE)); } /** * @param httpStack HTTP stack to be used * @param pool a buffer pool that improves GC performance in copy operations 可以自己来定义一个缓冲池 */ public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) { mHttpStack = httpStack; mPool = pool; } /** * 执行具体的网络请求 ,需要Volley的Request,返回的是可以被传递的响应 */ @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后没有执行上边的return 而当前又是一个while(true)循环,可以保证下面的请求重试的执行,是利用循环进行请求重试,请求重试策略只是记录重试的次数、超时 时间等内容。 } 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); } } } } /** * Logs requests that took over SLOW_REQUEST_THRESHOLD_MS to complete. * 如果该请求的时间超过了之前设置的时间,那么log下 */ private void logSlowRequests(long requestLifetime, Request<?> request, byte[] responseContents, StatusLine statusLine) { if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) { VolleyLog.d("HTTP response for request=<%s> [lifetime=%d], [size=%s], " + "[rc=%d], [retryCount=%s]", request, requestLifetime, responseContents != null ? responseContents.length : "null", statusLine.getStatusCode(), request.getRetryPolicy().getCurrentRetryCount()); } } /** * 请求重试策略 * Attempts to prepare the request for a retry. If there are no more attempts remaining in the * request's retry policy, a timeout exception is thrown. * @param request The request to use. */ private static void attemptRetryOnException(String logPrefix, Request<?> request, VolleyError exception) throws VolleyError { //获得该请求的请求重试策略 RetryPolicy retryPolicy = request.getRetryPolicy(); //请求重试策略的超时时间 int oldTimeout = request.getTimeoutMs(); try { //内部实现,重试次数+1 超时时间变化 //如果重试次数超过限定的最大次数,该方法抛出异常 retryPolicy.retry(exception); } catch (VolleyError e) { //当超过了最大重试次数,捕获到异常,给改请求添加标记 标记超时 request.addMarker( String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout)); //抛出异常 throw e; } //给请求添加标记,请求了多少次 request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout)); } /** * 从volley的请求中拿到头信息 * @Description * @param headers * @param entry * @date 2015年5月18日 下午2:32:06 */ private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) { // If there's no cache entry, we're done. 请求中没有实体,那么不做操作 if (entry == null) { return; } //如果 Request 中带有实体信息,如 Etag,Last-Modify 等,则进行缓存新鲜度的验证 if (entry.etag != null) { headers.put("If-None-Match", entry.etag); } //响应产生的时间 if (entry.serverDate > 0) { Date refTime = new Date(entry.serverDate); headers.put("If-Modified-Since", DateUtils.formatDate(refTime)); } } protected void logError(String what, String url, long start) { long now = SystemClock.elapsedRealtime(); VolleyLog.v("HTTP ERROR(%s) %d ms to fetch %s", what, (now - start), url); } /** Reads the contents of HttpEntity into a byte[]. 将响应的数据实体转为byte[]*/ private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError { //定义输出流 PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength()); byte[] buffer = null; try { InputStream in = entity.getContent(); if (in == null) { throw new ServerError(); } //从byte[]缓冲池中取字节数组 buffer = mPool.getBuf(1024); int count; while ((count = in.read(buffer)) != -1) { bytes.write(buffer, 0, count);//从buffer中读取内容写入输出流中的byte[]中 } return bytes.toByteArray(); } finally { try { // Close the InputStream and release the resources by "consuming the content". entity.consumeContent(); } catch (IOException e) { // This can happen if there was an exception above that left the entity in // an invalid state. VolleyLog.v("Error occured when calling consumingContent"); } //将字节数组返回到缓冲池中 mPool.returnBuf(buffer); //关闭输出流 bytes.close(); } } /** * Converts Headers[] to Map<String, String>. * 将响应的头信息解析出来转为map格式 */ private static Map<String, String> convertHeaders(Header[] headers) { Map<String, String> result = new HashMap<String, String>(); for (int i = 0; i < headers.length; i++) { result.put(headers[i].getName(), headers[i].getValue()); } return result; }}
0 0
- Android中的volley_4_执行网络请求的接口Network及其实现类BasicNetwork
- Volley源码学习(二):网络请求处理,HurlStack类,BasicNetwork类,ByteArrayPool,PoolingByteArrayOutputStream
- Android的接口回调在网络请求中的应用示例
- Android中的网络请求:
- 请求网络接口的工具类
- Android 网络请求实现
- iOS 依次执行 异步网络请求的一种实现
- Android HttpUtils网络请求工具类的实现
- Android HTTP网络请求的异步实现
- Android HTTP网络请求的异步实现
- Volley框架解析(四)-----Network接口及其默认实现类解析
- Android网络框架之Http请求的分发与执行
- 接口Set的特性及其实现类
- 谷歌Volley网络框架讲解——Network及其实现类
- 谷歌Volley网络框架讲解——Network及其实现类
- java中的AlgorithmParameterSpec接口及其IvParameterSpec实现类
- Android网络请求中的安全问题
- android中的网络请求框架
- WordPress文件目录结构详解
- C语言内存四区
- 详细说明phpmyadmin连接,管理多个mysql服务器
- C# 下实现UPD编程Demo
- cocos2d-x lua 实现状态机
- Android中的volley_4_执行网络请求的接口Network及其实现类BasicNetwork
- Servlet -- 跳转到页面后的绝对路径与相对路径的问题
- 图像编解码器
- Java集合类详解
- 4.18
- 南邮算法分析与设计实验3 回溯法
- iOS应用程序生命周期(前后台切换,应用的各种状态)详解
- int?id与id??1 的意思
- [Erlang]如何使用NIF