文章摘要
1窗市、volley 消息傳遞工 工作原理
附:獲取Volley源代碼
Demos案例源碼:https://github.com/HailouWang/DemosForApi
簡介:
volley有兩個主要的民工牛欢,CacheDispatcher以及NetworkDispatcher,也是兩個線程赃蛛,管理并處理Request任務(wù)恃锉。
volley為了保證大批量的網(wǎng)絡(luò)請求以及數(shù)據(jù)解析不會影響到主線程的用戶交互,使用了很多線程以及線程封裝技巧呕臂。包括這里的Cache破托。
在用戶發(fā)起網(wǎng)絡(luò)請求后,volley就將用戶的請求诵闭,丟到了本文介紹的緩存進(jìn)程炼团,緩存線程如果沒有能力處理,就丟給網(wǎng)絡(luò)線程疏尿,并告訴它瘟芝,老大需要數(shù)據(jù)結(jié)果,你趕緊去網(wǎng)絡(luò)上去拿褥琐。老大只要結(jié)果锌俱,不要過程。
主線程很忙敌呈,ResponseDelivery負(fù)責(zé)傳遞消息贸宏,伴君如伴虎,為了防止打擾到主線程的工作磕洪,ResponseDelivery也可以有一個線程吭练,在目前的源碼里,ResponseDelivery充分利用Handler的MessageQueue優(yōu)勢析显,管理并小心的將結(jié)果傳遞給主線程鲫咽。
那么,本文就來介紹下消息傳遞工(ResponseDelivery)的工作原理:
1谷异、傳遞工人(ResponseDelivery)初始化分尸。
在初始化RequestQueue工具類時,會初始化傳遞工歹嘹。傳遞工使用Handler來管理隊列箩绍,Handler的Looper來自主線程。
/**
* Creates the worker pool. Processing will not begin until {@link #start()} is called.
*創(chuàng)建一個工作池尺上,非start方法調(diào)用前材蛛,不會開始執(zhí)行
* @param cache A Cache to use for persisting responses to disk
* 1、緩存者尖昏。將相應(yīng)數(shù)據(jù)持久化到硬盤
* @param network A Network interface for performing HTTP requests
* 2仰税、網(wǎng)絡(luò)處理者。處理HTTP請求的Network 接口
* @param threadPoolSize Number of network dispatcher threads to create
* 3抽诉、網(wǎng)絡(luò)請求分發(fā)者陨簇。默認(rèn)4個分發(fā)線程池
* @param delivery A ResponseDelivery interface for posting responses and errors
* 4、響應(yīng)傳遞者。傳遞響應(yīng)數(shù)據(jù)河绽,以及錯誤日志信息
*/
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}
/**
* Creates the worker pool. Processing will not begin until {@link #start()} is called.
*
* @param cache A Cache to use for persisting responses to disk
* @param network A Network interface for performing HTTP requests
* @param threadPoolSize Number of network dispatcher threads to create
*/
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
this(cache, network, threadPoolSize,
new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
在這里己单,原生提供了一種默認(rèn)的實現(xiàn):
new ExecutorDelivery(new Handler(Looper.getMainLooper()))
在這段代碼中,需要傳入一個Handler對象耙饰,對象中的Loop來自主線程纹笼,可以這么說,Handler工作在主線程中苟跪。
備注:我們也可以創(chuàng)建自己的傳遞工(ResponseDelivery)廷痘,原生提供的實現(xiàn)中,類圖如下:
2件已、傳遞工人(ResponseDelivery)接收回調(diào)任務(wù)笋额。
我們之前介紹過了,volley有兩個默默工作的勞工篷扩,它們就是CacheDispatcher以及NetworkDispatcher兄猩,勞工們在做完工作后,是沒有權(quán)利告訴主線程的鉴未,因為這是傳遞工人的工作枢冤。
NetworkDispatcher或者CacheDispatcher通過如下方式告訴ResponseDelivery,需要向主線程傳遞結(jié)果铜秆。
mDelivery.postResponse(request, response);
無論是Response還是Error淹真,所有的這些響應(yīng)都發(fā)給了ResponseDelivery中的線程池。
3连茧、傳遞工人對接收到的任務(wù)的處理
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);
}
};
}
@Override
public void postResponse(Request<?> request, Response<?> response) {
postResponse(request, response, null);
}
@Override
public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
request.markDelivered();
request.addMarker("post-response");
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
}
@Override
public void postError(Request<?> request, VolleyError error) {
request.addMarker("post-error");
Response<?> response = Response.error(error);
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null));
}
線程池會將得到的消息趟咆,包裝一個Runnable,利用Handler發(fā)送給主線程梅屉。
// If this request has canceled, finish it and don't deliver.
//1、如果請求已經(jīng)取消鳞贷,則不必傳遞
if (mRequest.isCanceled()) {
mRequest.finish("canceled-at-delivery");
return;
}
// Deliver a normal response or error, depending.
if (mResponse.isSuccess()) {
//2坯汤、如果Response沒有錯誤,則分發(fā)result
mRequest.deliverResponse(mResponse.result);
} else {
//3搀愧、如果Reponse有錯誤惰聂,則分發(fā)error
mRequest.deliverError(mResponse.error);
}
// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
//4、如果 響應(yīng)屬于媒介咱筛,標(biāo)記marker
if (mResponse.intermediate) {
mRequest.addMarker("intermediate-response");
} else {
mRequest.finish("done");
}
4搓幌、傳遞工人將消息回調(diào)給主線程。
通過3中可以看到迅箩,發(fā)往主線程的回調(diào)溉愁,是通過mRequest.deliverResponse來實現(xiàn)的。
/**
* Subclasses must implement this to perform delivery of the parsed
* response to their listeners. The given response is guaranteed to
* be non-null; responses that fail to parse are not delivered.
* @param response The parsed response returned by
* {@link #parseNetworkResponse(NetworkResponse)}
*/
abstract protected void deliverResponse(T response);
通過Request#deliverResponse饲趋,我們看到拐揭,這是一個Abstract方法撤蟆,不同的實現(xiàn),傳遞方式也不同堂污。這里介紹下原生的實現(xiàn):
StringRequest.java
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}