谷歌Volley网络框架讲解——Network及其实现类
我们看到Network接口只有一个实现类BasicNetwork,而HttpStack有两个实现类。

BasicNetwork这个类是toolbox工具箱包里的,实现了Network接口。
先来看下Network这个interface,performRequest(Request*)执行一个请求,以一个Request为参数,返回一个
NetworkResponse 。
public interface Network {
/**
* Performs the specified request.执行这个请求
* @param request Request to process//待处理的请求
* @return A {@link NetworkResponse} with data and caching metadata; will never be null
* 返回一个请求结果,不会为空
* @throws VolleyError on errors
*/
public NetworkResponse performRequest(Request<?> request) throws VolleyError;
}
BasicNetwork实现了Network接口,我们来看下UML图。

再来看下它的构造函数,两个参数HttpStack和ByteArrayPool,这两个参数就是主要的成员变量。
/**
* 带一个默认大小的ByteArrayPool缓冲池
* @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));
} /**
* 主构造方法BasicNetwork(HttpStack*,ByteArrayPool*)
* @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;
}
再看看哪个方法用到了mHttpStack,就是在实现Network接口的performRequest()方法,并且mHttpStack有个跟Network接口同名的方法,这才是真正执行请求的方法,也是直接传入请求返回响应。
而mPool是在entityToBytes()这个方法中用到,顾名思义这个方法就是把HttpEntity转换为bytes数据,而这个缓存池就是为便捷转换数据格式。
再详细看下最重要的方法performRequest(),代码中均以加上注释,见解有误望读者们见谅和请教。
/**
* @title performRequest执行各种Request请求并以NetworkResponse的形式返回结果
* @param Request
* @return NetworkResponse
* @throws VolleyError
* 定义:{@link Network#performRequest(Request)}
* 被调:{@link NetworkDispatcher#run()}
*
*/
@Override//NetworkDispatcher的run()方法中调用
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();//开始请求时间
while (true) {
HttpResponse httpResponse = null;//apache的请求结果
byte[] responseContents = null;//请求的内容
Map<String, String> responseHeaders = new HashMap<String, String>();//响应结果头部信息
try {
// Gather headers.
Map<String, String> headers = new HashMap<String, String>();//保存缓存数据
addCacheHeaders(headers, request.getCacheEntry());//先获取缓存数据
httpResponse = mHttpStack.performRequest(request, headers);//去调用mHttpStack的实现方法执行请求
StatusLine statusLine = httpResponse.getStatusLine();//获取http状态线
int statusCode = statusLine.getStatusCode();//获取状态码 responseHeaders = convertHeaders(httpResponse.getAllHeaders());
// Handle cache validation.//处理缓存验证
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//返回缓存数据
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
request.getCacheEntry().data, responseHeaders, true);
} //把HttpEntity转化为byte[]数据
responseContents = entityToBytes(httpResponse.getEntity());
// if the request is slow, log it.//如果请求很慢,就打印出来看一下
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
logSlowRequests(requestLifetime, request, responseContents, statusLine);//打印 //连接正常但是返回无内容,抛出IO异常
if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT) {
throw new IOException();
}
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) {//Bad URL
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {//IO异常
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {//如果没有返回httpResponse,就说明没连接
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);//只有状态码为5XX才抛出服务器异常
}
} else {//网络异常
throw new NetworkError(networkResponse);
}
}
}
}
A:先是通过mHttpStack把请求执行并且获取它的响应结果,根据HttpStatus做出各种判断。
B:然后再把httpResponse的Entity转化为ByteArray,并处理各种发生的异常。
C:最后的过程是这样的:通过Volley创建一个RequestQueue请求队列,当这个队列开始运作的时候会启动NetworkDispatcher这个工作线程,而BasicNetwork的performRequest()的方法就在NetworkDispatcher线程run()方法中调用,然后通过mHttpStack的performRequest()方法获取一个networkResponse,在NetworkDispatcher线程把这个networkResponse转化为期望的数据类型,比如Response<String>,Response<Json>,Response<Bitmap>。
谷歌Volley网络框架讲解——Network及其实现类的更多相关文章
- 谷歌Volley网络框架讲解——HttpStack及其实现类
前两篇已经对网络请求流程已经梳理了个大概,这次我们着重看一下HttpStack和它的其实现类.我们之前在Network篇讲过它仅有一个实现类,而今天我们讲的HttpStack有两个实现类. 其中Htt ...
- 谷歌Volley网络框架讲解——BasicNetwork类
谷歌Volley网络框架讲解——BasicNetwork类 这个类是toolbox工具箱包里的,实现了Network接口. 先来看下Network这个interface,performRequest( ...
- 谷歌Volley网络框架讲解——第一篇
自从公司新招了几个android工程师后,我清闲了些许.于是就可以有时间写写博客,研究一些没来的研究的东西. 今年的谷歌IO大会上,谷歌推出了自己的网络框架——Volley.不久前就听说了但是没有cl ...
- 谷歌Volley网络框架讲解——网络枢纽
研究了这么久的Volley,愈来愈发现这个框架的精美和人性化.比起民间一些框架强很多,一开始总是盲人摸象找不到头绪,现在终于有些明朗了.Volley其实就是一个请求队列的代理类,我们看下UML. 这就 ...
- Volley网络框架的使用
Volley的特点: 使用网络通信更快.更简单 Get/Post网络请求网络图像的高效率异步请求 可以对网络请求的优先级进行排序处理 可以进行网络请求的缓存 可以取消多级别请求 可以和Activi ...
- Volley网络框架完全解析(使用篇)
在Android中,网络请求无非就这两种:HttpURLConnection和HttpClient( Apache),我们在使用时一般都会对它们进行一系列的封装,但是这过程不免有些繁琐,所以,Goog ...
- Volley网络框架完全解析(实战篇)
好了,今天就通过一个瀑布流demo,来使用Volley框架请求网络图片. 前言: 我们使用NetworkImageView显示图片: 1.因为该控件可以自动的管理好请求的生命周期,当与父控件detac ...
- Volley网络框架完全解析(缓存篇)
在上一篇中讲完了Volley框架怎么使用,那么这篇就来讲讲Volley框架的缓存机制 我们看Volley内部源码发现: Volley框架内部自己处理了DiskBasedCache硬盘缓存,但是没有处理 ...
- Android网络框架源码分析一---Volley
转载自 http://www.jianshu.com/p/9e17727f31a1?utm_campaign=maleskine&utm_content=note&utm_medium ...
随机推荐
- Required field 'client_protocol' is unset! Struct:TOpenSessionReq(client_protocol:null, configuration:{use:database=default}) (state=08S01,code=0)
sparksql 2.和hive2.1.1 由于sparksql中的hive-cli 等包的版本是1.2的需要自己下载,下载替换之后不报错,替换之前做好备份
- 专题实验 Statspack & 9大动态视图
statspack 是一个DBA经常用的调优工具, 它的主要作用是, 针对数据库的不同时刻做快照, 然后来比对快照之前的差异和瓶颈, 快照可以是手动的也可以是自动的, 从 oracle 10g开始, ...
- 【R】用 ggplot2 绘制漂亮的分级统计地图
最近我一直尝试利用R绘制地图,我从网上找到了上百种不同的实现方法,然而其中却没有适用于我的数据的方法.最终,我从以下几个博客[1]中找到了灵感.我在整合这些资源的基础上,通过不断的试验和修正得到了一个 ...
- 受打击了:你是学.net 的吧?
我在网上投了简历,今天去面试, 去到才知道有面试题做,做完之后自知答的很烂. 没想到面试我的那个人,一开始就很直接,说: 我感觉你很喜欢用英语, 但英语很烂 我觉得你很喜欢用别人的东西, 但技术水平很 ...
- 试读《基于MVC的JavaScript Web富应用开发》— 不一样的JavaScript
前言 <基于MVC的JavaScript Web富应用开发>是ItEye在7月份发起试读的书.下载了试读的章节,发现只有全本的开始到第二章,第一章很简洁明了地讲述了JavaScript的历 ...
- python中的高阶函数
高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...
- vlc player验证交换机igmp
使用vlc media player发送多播数据,验证交换机igmp的设置是否成功. 链接 http://peakdrive.com/?p=440 http://www.dasblinkenlicht ...
- 在linux上开发210的hdmi-servers输出
这段时间一直在研究hdmi-servers,因为友善对这个在是闭源的,所以由于兴趣的关系和工作的关系,决定自己写一个hdmi-servers. 在hdmi中,最关键的是弄清楚了Hdmi显示数据的怎么来 ...
- hdu 5044 树区间操作最后输出/ lca+dfs
题意:一棵树,俩种操作:1 有路径上的全部点加vi,2全部边加vi. 先离线求出全部询问的lca,再遍历询问一次,点+vi,lca-2*vi ,最后dfs从叶子扫上来一次,最后再祖先点补上就可以.用了 ...
- PHPExcel正确读取excel表格时间单元格(转载)
error_reporting(E_ALL); date_default_timezone_set('Asia/shanghai'); /** PHPExcel_IOFactory */ requir ...