請求結果的交付是通過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 the21 // 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 the15 * 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 @Override31 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 done46 // 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 @Override2 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 @Override5 public void execute(Runnable command) {6 handler.post(command);7 }8 };9 }