這篇文章主要分析網絡請求和結果交付的過程。html
以前已經說到經過mNetWork.performRequest()方法來獲得NetResponse,看一下該方法具體的執行流程,performRequest是一個接口方法,真正實現該方法以及被調用的是BasicNetWork,其具體的performRequest代碼以下:緩存
@Override public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; byte[] responseContents = null; Map<String, String> responseHeaders = Collections.emptyMap(); try { // Gather headers. 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()); // Handle cache validation. if (statusCode == HttpStatus.SC_NOT_MODIFIED) { Entry entry = request.getCacheEntry(); if (entry == null) { return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } // A HTTP 304 response does not have all header fields. We // have to use the header fields from the cache entry plus // the new ones from the response. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 entry.responseHeaders.putAll(responseHeaders); return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } // Some responses such as 204s do not have content. We must check. if (httpResponse.getEntity() != null) { responseContents = entityToBytes(httpResponse.getEntity()); } else { // Add 0 byte response as a way of honestly representing a // no-content request. responseContents = new byte[0]; } // if the request is slow, log it. long requestLifetime = SystemClock.elapsedRealtime() - requestStart; logSlowRequests(requestLifetime, request, responseContents, statusLine); if (statusCode < 200 || statusCode > 299) { throw new IOException(); } return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); } catch (SocketTimeoutException e) { attemptRetryOnException("socket", request, new TimeoutError()); } catch (ConnectTimeoutException e) { attemptRetryOnException("connection", request, new TimeoutError()); } catch (MalformedURLException e) { throw new RuntimeException("Bad URL " + request.getUrl(), e); } catch (IOException e) { int statusCode; if (httpResponse != null) { statusCode = httpResponse.getStatusLine().getStatusCode(); } else { throw new NoConnectionError(e); } VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl()); NetworkResponse networkResponse; if (responseContents != null) { networkResponse = new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) { attemptRetryOnException("auth", request, new AuthFailureError(networkResponse)); } else if (statusCode >= 400 && statusCode <= 499) { // Don't retry other client errors. throw new ClientError(networkResponse); } else if (statusCode >= 500 && statusCode <= 599) { if (request.shouldRetryServerErrors()) { attemptRetryOnException("server", request, new ServerError(networkResponse)); } else { throw new ServerError(networkResponse); } } else { // 3xx? No reason to retry. throw new ServerError(networkResponse); } } else { attemptRetryOnException("network", request, new NetworkError()); } } } }
上述代碼能夠看出,真正進行網絡請求仍是HttpStack.performRequest,在請求結束之後,對返回的狀態碼進行封裝,這裏主要說一下304狀態碼,該狀態碼,因爲只返回header,不返回body,所以body須要從之前緩存的entity中取出body。而HttpStack的兩個實現類一個是HttpClientStack,另外一個是HurlStack,他們也是直接調用Java自帶的http請求方法來獲得response。
下面要看的是NetWorkResponse的封裝網絡
public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, boolean notModified, long networkTimeMs) { this.statusCode = statusCode; this.data = data; this.headers = headers; this.notModified = notModified; this.networkTimeMs = networkTimeMs; }
這就是所有的NetWorkResponse的封裝,封裝的目的是爲了對response進行交付。socket
ResponseDelivery是一個接口,其定義了3個方法,2個傳遞response的重載方法與一個傳遞error方法ide
/** * Parses a response from the network or cache and delivers it. */ void postResponse(Request<?> request, Response<?> response); /** * Parses a response from the network or cache and delivers it. The provided * Runnable will be executed after delivery. */ void postResponse(Request<?> request, Response<?> response, Runnable runnable); /** * Posts an error for the given request. */ void postError(Request<?> request, VolleyError error);
其實現類ExecutorDelivery是真正執行的功能類。其內部很是簡單,代碼以下:post
public class ExecutorDelivery implements ResponseDelivery { /** Used for posting responses, typically to the main thread. */ private final Executor mResponsePoster; /** * Creates a new response delivery interface. * @param handler {@link Handler} to post responses on */ 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); } }; } /** * Creates a new response delivery interface, mockable version * for testing. * @param executor For running delivery tasks */ public ExecutorDelivery(Executor executor) { mResponsePoster = executor; } @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)); } /** * A Runnable used for delivering network responses to a listener on the * main thread. */ @SuppressWarnings("rawtypes") private class ResponseDeliveryRunnable implements Runnable { private final Request mRequest; private final Response mResponse; private final Runnable mRunnable; public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { mRequest = request; mResponse = response; mRunnable = runnable; } @SuppressWarnings("unchecked") @Override public void run() { // If this request has canceled, finish it and don't deliver. if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; } // Deliver a normal response or error, depending. if (mResponse.isSuccess()) { mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); } // If this is an intermediate response, add a marker, otherwise we're done // and the request can be finished. if (mResponse.intermediate) { mRequest.addMarker("intermediate-response"); } else { mRequest.finish("done"); } // If we have been provided a post-delivery runnable, run it. if (mRunnable != null) { mRunnable.run(); } } } }
其構造方法惟一目的就是實例化了Excutor類型的mResponsePoster,Volley默認調用的是第一個構造方法,也就是包裝了一個Handler.該類最主要的方法是postResponse,其核心的實現this
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
執行的是ResponseDeliveryRunnable的run方法,而run方法中是經過url
mRequest.deliverResponse(mResponse.result);
而Request的該方法則是由有其具體的實現類 StringRequest
,JsonRequest
,ImageRequest
實現,其實現都一致,則是spa
@Override protected void deliverResponse(T response) { mListener.onResponse(response); }
調用回調方法。.net
所以,整個分發過程就清晰了,經過Dispatcher進行處理的每一個Request,對request進行處理完,則經過ResponseDelivery進行交付,其交付經過獲得一個UI線程的handler,經過該Handler的post,調用Request類的delivery方法,在該方法中,又會調用咱們構造request時,傳入的回調方法。