請求結果的交付是通過ResponseDelivery接口完成的,它有一個實現類ExecutorDelivery, 主要有postResponse()與postError()兩個方法,分別在請求成功或失敗時將結果提交給請求發起者。
1. 首先,在NetworkDispatcher的run()方法中,當服務器返回響應並解析完後,會調用mDelivery.postResponse(request, response);來提交請求響應。
復制代碼
1 @Override
2 public void run() {
3 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
4 Request<?> request;
5 while (true) {
6 try {
7 // Take a request from the queue.
8 request = mQueue.take();
9 } catch (InterruptedException e) {
10 // We may have been interrupted because it was time to quit.
11 if (mQuit) {
12 return;
13 }
14 continue;
15 }
16
17 try {
18 request.addMarker("network-queue-take");
19
20 // If the request was cancelled already, do not perform the
21 // network request.
22 if (request.isCanceled()) {
23 request.finish("network-discard-cancelled");
24 continue;
25 }
26
27 addTrafficStatsTag(request);
28
29 // Perform the network request.
30 NetworkResponse networkResponse = mNetwork.performRequest(request);
31 request.addMarker("network-http-complete");
32
33 // If the server returned 304 AND we delivered a response already,
34 // we're done -- don't deliver a second identical response.
35 if (networkResponse.notModified && request.hasHadResponseDelivered()) {
36 request.finish("not-modified");
37 continue;
38 }
39
40 // Parse the response here on the worker thread.
41 Response<?> response = request.parseNetworkResponse(networkResponse);
42 request.addMarker("network-parse-complete");
43
44 // Write to cache if applicable.
45 // TODO: Only update cache metadata instead of entire record for 304s.
46 if (request.shouldCache() && response.cacheEntry != null) {
47 mCache.put(request.getCacheKey(), response.cacheEntry);
48 request.addMarker("network-cache-written");
49 }
50
51 // Post the response back.
52 request.markDelivered();
53 mDelivery.postResponse(request, response);
54 } catch (VolleyError volleyError) {
55 parseAndDeliverNetworkError(request, volleyError);
56 } catch (Exception e) {
57 VolleyLog.e(e, "Unhandled exception %s", e.toString());
58 mDelivery.postError(request, new VolleyError(e));
59 }
60 }
61 }
復制代碼
2. 看ExecutorDelivery中postResponse()方法的具體實現。其中mResponsePoster是一個Executor。每post一個response,都會調用ResponseDeliveryRunnable的run()方法。在這個run()方法中,會通過mRequest.deliverResponse(mResponse.result)來傳遞response的result,這個result其實就是已經解析好的響應結果,比如一個表示處理結果的字符串或一個User對象。
復制代碼
1 @Override
2 public void postResponse(Request<?> request, Response<?> response) {
3 postResponse(request, response, null);
4 }
5
6 @Override
7 public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
8 request.markDelivered();
9 request.addMarker("post-response");
10 mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
11 }
12
13 /**
14 * A Runnable used for delivering network responses to a listener on the
15 * main thread.
16 */
17 @SuppressWarnings("rawtypes")
18 private class ResponseDeliveryRunnable implements Runnable {
19 private final Request mRequest;
20 private final Response mResponse;
21 private final Runnable mRunnable;
22
23 public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
24 mRequest = request;
25 mResponse = response;
26 mRunnable = runnable;
27 }
28
29 @SuppressWarnings("unchecked")
30 @Override
31 public void run() {
32 // If this request has canceled, finish it and don't deliver.
33 if (mRequest.isCanceled()) {
34 mRequest.finish("canceled-at-delivery");
35 return;
36 }
37
38 // Deliver a normal response or error, depending.
39 if (mResponse.isSuccess()) {
40 mRequest.deliverResponse(mResponse.result);
41 } else {
42 mRequest.deliverError(mResponse.error);
43 }
44
45 // If this is an intermediate response, add a marker, otherwise we're done
46 // and the request can be finished.
47 if (mResponse.intermediate) {
48 mRequest.addMarker("intermediate-response");
49 } else {
50 mRequest.finish("done");
51 }
52
53 // If we have been provided a post-delivery runnable, run it.
54 if (mRunnable != null) {
55 mRunnable.run();
56 }
57 }
58 }
復制代碼
3. 既然是通過Request的deliverResponse()來傳遞響應結果,就來看下這個方法, 第二篇中已經知道這個方法是個抽象函數,由它子類來實現。以第一篇中的MyGsonRequest為例,其實現很簡單,就是調用了mListener的onResponse方法。
1 @Override
2 protected void deliverResponse(T response) {
3 mListener.onResponse(response);
4 }
這個mListener就是在主線程實例化MyGsonRequest的時候,傳過來的一個Response.Listener<T>實例,這是MyGsonRequest的構造函數:
復制代碼
1 public MyGsonRequest(int method
2 , String url
3 , Object requestBody
4 , Class<T> responseClass
5 , Listener<T> listener
6 , ErrorListener errorListener) {
7
8 super(method, url, errorListener);
9 this.mRequestBody = requestBody;
10 this.mResponseClass = responseClass;
11 this.mListener = listener;
12 mGson = new Gson();
13
14 }
復制代碼
這裡mListener也就是第一篇中在主線程中通過createRegisterSuccessListener函數返回的監聽器實例,如下代碼所示。 所以最終會調到這裡的onResponse()方法,來做一些更新UI或提示用戶請求成功之類的操作。請求失敗時,響應錯誤結果的提交與之類似。這樣,Volley就完成了響應結果的交付。
復制代碼
1 private Listener<String> createRegisterSuccessListener() {
2 return new Listener<String>() {
3 @Override
4 public void onResponse(String response) {
5 if (mProgressDialog != null) {
6 mProgressDialog.dismiss();
7 }
8 Toast.makeText(
9 RegisterActivity.this,
10 getString(R.string.msg_register_success),
11 Toast.LENGTH_SHORT).show();
12
13 }
14 };
15 }
復制代碼
這裡還有一個問題, 因為更新UI的操作只能在主線程中進行,那麼ResponseDeliveryRunnable的run()方法不能再新起一個線程來執行,而應該在主線程中執行,這個是如何做到的?
其實還是用的Handler,Looper,MessageQueue的那套機制。 在Volley初始化一個RequestQueue的時候,會調用RequestQueue的如下構造函數,它構建了一個ExecutorDelivery對象,並把一個與主線程的Looper關聯的一個Handler,
1 public RequestQueue(Cache cache, Network network, int threadPoolSize) {
2 this(cache, network, threadPoolSize,
3 new ExecutorDelivery(new Handler(Looper.getMainLooper())));
4 }
然後再看下ExecutorDelivery的構造方法, 通過handler的post方法,把ResponseDeliveryRunnable 這個runnable加到了主線程的消息隊列中,所以它的run()方法是在主線程中執行的。
復制代碼
1 public ExecutorDelivery(final Handler handler) {
2 // Make an Executor that just wraps the handler.
3 mResponsePoster = new Executor() {
4 @Override
5 public void execute(Runnable command) {
6 handler.post(command);
7 }
8 };
9 }