Volley 的主要特點
(1). 擴展性強拧揽。Volley 中大多是基于接口的設(shè)計剩檀,可配置性強。
(2). 一定程度符合 Http 規(guī)范葵诈,包括返回 ResponseCode(2xx塑悼、3xx劲适、4xx、5xx)的處理厢蒜,請求頭的處理霞势,緩存機制的支持等烹植。并支持重試及優(yōu)先級定義。
(3). 默認(rèn) Android2.3 及以上基于 HttpURLConnection愕贡,2.3 以下基于 HttpClient 實現(xiàn)草雕,這兩者的區(qū)別及優(yōu)劣在4.2.1 Volley中具體介紹。
(4). 提供簡便的圖片加載工具固以。
整體框架
1墩虹、設(shè)計圖
上面是 Volley 的總體設(shè)計圖,主要是通過兩種
Dispatch Thread
不斷從RequestQueue
中取出請求嘴纺,根據(jù)是否已緩存調(diào)用Cache
或Networ
k這兩類數(shù)據(jù)獲取接口之一败晴,從內(nèi)存緩存或是服務(wù)器取得請求的數(shù)據(jù)浓冒,然后交由ResponseDelivery去做結(jié)果分發(fā)及回調(diào)處理栽渴。
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 選擇網(wǎng)絡(luò)請求API
網(wǎng)絡(luò)請求(API Level >= 9) 基于 HttpURLConnection 的 HurlStack闲擦,當(dāng)其小于 9,采用基于 HttpClient 的 HttpClientStack场梆。這兩個都是實現(xiàn)了HttpStack墅冷,它的功能是完成網(wǎng)絡(luò)請求并返回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 解析網(wǎng)絡(luò)響應(yīng)
在BasicNetwork的performRequest(Request<?> request)方法中或油,獲取HttpResponse對象寞忿,解析出響應(yīng)碼、響應(yīng)內(nèi)容顶岸、響應(yīng)頭等信息腔彰,之后將其封裝成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 任務(wù)調(diào)度
Volley 框架的核心類辖佣,將請求 Request 加入到一個運行的RequestQueue中霹抛,來完成請求操作。
(1). 主要成員變量
RequestQueue 中維護了兩個基于優(yōu)先級的 Request
隊列卷谈,緩存請求隊列和網(wǎng)絡(luò)請求隊列杯拐。
放在緩存請求隊列中的 Request,將通過緩存獲取數(shù)據(jù)世蔗;放在網(wǎng)絡(luò)請求隊列中的 Request端逼,將通過網(wǎng)絡(luò)獲取數(shù)據(jù)。
PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<?>>(); PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<Request<?>>();
維護了一個正在進行中污淋,尚未完成的請求集合裳食。
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
維護了一個等待請求的集合,如果一個請求正在被處理并且可以被緩存芙沥,后續(xù)的相同 url 的請求诲祸,將進入此等待隊列浊吏。
private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
(2). 啟動隊列
創(chuàng)建出 RequestQueue 以后,調(diào)用 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中取任務(wù)墩衙,并調(diào)用mNetwork.performRequest進行執(zhí)行,將返回的網(wǎng)絡(luò)信息交由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;
/**
* 一旦調(diào)用quit方法漆改,mQuit為true,會發(fā)生InterruptedException異常,就會在run方法中被攔截到准谚,
由于mQuit是線程間可見挫剑,所以當(dāng)前線程就退出了。
*/
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柱衔、任務(wù)添加
通過請求隊列中的add方法進行添加樊破,簡單點就是有緩存請求,就進行緩存任務(wù)調(diào)度唆铐,否則就使用網(wǎng)絡(luò)任務(wù)調(diào)度(NetworkDispatcher)哲戚。
3、緩存
Volley 構(gòu)建了一套相對完整的符合 Http 語義的緩存機制艾岂。
優(yōu)點和特點
(1). 根據(jù)Cache-Control和Expires首部來計算緩存的過期時間顺少。如果兩個首部都存在情況下,以Cache-Control為準(zhǔn)王浴。
(2). 利用If-None-Match和If-Modified-Since對過期緩存或者不新鮮緩存脆炎,進行請求再驗證,并處理 304 響應(yīng)叼耙,更新緩存腕窥。
(3). 默認(rèn)的緩存實現(xiàn),將緩存以文件的形式存儲在 Disk筛婉,程序退出后不會丟失簇爆。
4、響應(yīng)處理
通過handler進行數(shù)據(jù)在主線程顯示爽撒,數(shù)據(jù)處理使用的是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);
}
};
}