Volley 的主要特点
(1). 扩展性强。Volley 中大多是基于接口的设计,可配置性强。
(2). 一定程度符合 Http 规范,包括返回 ResponseCode(2xx、3xx、4xx、5xx)的处理,请求头的处理,缓存机制的支持等。并支持重试及优先级定义。
(3). 默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现,这两者的区别及优劣在4.2.1 Volley中具体介绍。
(4). 提供简便的图片加载工具。
整体框架
1、设计图
上面是 Volley 的总体设计图,主要是通过两种
Dispatch Thread
不断从RequestQueue
中取出请求,根据是否已缓存调用Cache
或Networ
k这两类数据获取接口之一,从内存缓存或是服务器取得请求的数据,然后交由ResponseDelivery去做结果分发及回调处理。
1、初始化
Volley类中newRequestQueue初始化部分。
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
- 1.1 选择网络请求API
网络请求(API Level >= 9) 基于 HttpURLConnection 的 HurlStack,当其小于 9,采用基于 HttpClient 的 HttpClientStack。这两个都是实现了HttpStack,它的功能是完成网络请求并返回HttpResponse类。
public interface HttpStack {
/**
* Performs an HTTP request with the given parameters.
* @param request the request to perform
* @param additionalHeaders additional headers to be sent together with
* {@link Request#getHeaders()}
* @return the HTTP response
*/
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError;
}
- 1.2 解析网络响应
在BasicNetwork的performRequest(Request<?> request)方法中,获取HttpResponse对象,解析出响应码、响应内容、响应头等信息,之后将其封装成NetworkResponse对象。
public NetworkResponse performRequest(Request<?> request){
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = new HashMap<String, String>();
Map<String, String> headers = new HashMap<String, String>();
addCacheHeaders(headers, request.getCacheEntry());
httpResponse = mHttpStack.performRequest(request, headers);
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
responseHeaders = convertHeaders(httpResponse.getAllHeaders());
responseContents = entityToBytes(httpResponse.getEntity());
return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
}
- 1.3 任务调度
Volley 框架的核心类,将请求 Request 加入到一个运行的RequestQueue中,来完成请求操作。
(1). 主要成员变量
RequestQueue 中维护了两个基于优先级的 Request
队列,缓存请求队列和网络请求队列。
放在缓存请求队列中的 Request,将通过缓存获取数据;放在网络请求队列中的 Request,将通过网络获取数据。
PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<?>>(); PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<Request<?>>();
维护了一个正在进行中,尚未完成的请求集合。
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
维护了一个等待请求的集合,如果一个请求正在被处理并且可以被缓存,后续的相同 url 的请求,将进入此等待队列。
private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
(2). 启动队列
创建出 RequestQueue 以后,调用 start 方法,启动队列。
public void start() {
stop(); // Make sure any currently running dispatchers are stopped.
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
NetworkDispatcher是一个线程类,采用的是RequestQueue的mNetworkQueue对列作为阻塞对列。在run方法里面不断从mNetworkQueue中取任务,并调用mNetwork.performRequest进行执行,将返回的网络信息交由ResponseDelivery处理。
public class NetworkDispatcher extends Thread {
private final BlockingQueue<Request<?>> mQueue;
private final ResponseDelivery mDelivery;
/** Used for telling us to die. */
private volatile boolean mQuit = false;
/**
* 一旦调用quit方法,mQuit为true,会发生InterruptedException异常,就会在run方法中被拦截到,
由于mQuit是线程间可见,所以当前线程就退出了。
*/
public void quit() {
mQuit = true;
interrupt();
}
@Override
public void run() {
Request<?> request;
while (true) {
try {
// Take a request from the queue.
request = mQueue.take();
} catch (InterruptedException e) {
if (mQuit) {
return;
}
continue;
}
NetworkResponse networkResponse = mNetwork.performRequest(request);
// Parse the response here on the worker thread.
Response<?> response = request.parseNetworkResponse(networkResponse);
mDelivery.postResponse(request, response);
}
}
}
2、任务添加
通过请求队列中的add方法进行添加,简单点就是有缓存请求,就进行缓存任务调度,否则就使用网络任务调度(NetworkDispatcher)。
3、缓存
Volley 构建了一套相对完整的符合 Http 语义的缓存机制。
优点和特点
(1). 根据Cache-Control和Expires首部来计算缓存的过期时间。如果两个首部都存在情况下,以Cache-Control为准。
(2). 利用If-None-Match和If-Modified-Since对过期缓存或者不新鲜缓存,进行请求再验证,并处理 304 响应,更新缓存。
(3). 默认的缓存实现,将缓存以文件的形式存储在 Disk,程序退出后不会丢失。
4、响应处理
通过handler进行数据在主线程显示,数据处理使用的是ExecutorDelivery。
public ExecutorDelivery(final Handler handler) {
// Make an Executor that just wraps the handler.
mResponsePoster = new Executor() {
@Override
public void execute(Runnable command) {
handler.post(command);
}
};
}