從上圖能夠看到Volley分爲三個線程,分別是主線程、緩存調度線程、和網絡調度線程,首先請求會加入緩存隊列,若是發現能夠找到相應的緩存結果就直接讀取緩存並解析,而後回調給主線程;若是在緩存中沒有找到結果,則將這條請求加入到網絡隊列中,而後發送HTTP請求,解析響應並寫入緩存,並回調給主線程。android
咱們都知道使用Volley以前首先要建立RequestQueue:緩存
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
這也是volley運做的入口,看看newRequestQueue:網絡
public static RequestQueue newRequestQueue(Context context) { return newRequestQueue(context, (HttpStack)null); } public static RequestQueue newRequestQueue(Context context, HttpStack stack) { return newRequestQueue(context, stack, -1); }
連續調用了兩個重載函數,最終調用的是:ide
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { File cacheDir = new File(context.getCacheDir(), "volley"); String userAgent = "volley/0"; try { String network = context.getPackageName(); PackageInfo queue = context.getPackageManager().getPackageInfo(network, 0); userAgent = network + "/" + queue.versionCode; } catch (NameNotFoundException var7) { ; } if(stack == null) { if(VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } BasicNetwork network1 = new BasicNetwork((HttpStack)stack); RequestQueue queue1; if(maxDiskCacheBytes <= -1) { queue1 = new RequestQueue(new DiskBasedCache(cacheDir), network1); } else { queue1 = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network1); } queue1.start(); return queue1; }
能夠看到若是android版本大於等於2.3則調用基於HttpURLConnection的HurlStack,不然就調用基於HttpClient的HttpClientStack。並建立了RequestQueue,調用了start()方法:函數
public void start() { this.stop(); this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery); this.mCacheDispatcher.start(); for(int i = 0; i < this.mDispatchers.length; ++i) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery); this.mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } }
CacheDispatcher是緩存調度線程,並調用了start()方法,在循環中調用了NetworkDispatcher的start()方法,NetworkDispatcher是網絡調度線程,默認狀況下mDispatchers.length爲4,默認開啓了4個網絡調度線程,也就是說有5個線程在後臺運行並等待請求的到來。接下來咱們建立各類的Request,並調用RequestQueue的add()方法:post
public <T> Request<T> add(Request<T> request) { request.setRequestQueue(this); Set var2 = this.mCurrentRequests; synchronized(this.mCurrentRequests) { this.mCurrentRequests.add(request); } request.setSequence(this.getSequenceNumber()); request.addMarker("add-to-queue"); //若是不能緩存,則將請求添加到網絡請求隊列中 if(!request.shouldCache()) { this.mNetworkQueue.add(request); return request; } else { Map var8 = this.mWaitingRequests; synchronized(this.mWaitingRequests) { String cacheKey = request.getCacheKey(); //以前是否有執行相同的請求且尚未返回結果的,若是有的話將此請求加入mWaitingRequests隊列,再也不重複請求 if(this.mWaitingRequests.containsKey(cacheKey)) { Object stagedRequests = (Queue)this.mWaitingRequests.get(cacheKey); if(stagedRequests == null) { stagedRequests = new LinkedList(); } ((Queue)stagedRequests).add(request); this.mWaitingRequests.put(cacheKey, stagedRequests); if(VolleyLog.DEBUG) { VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", new Object[]{cacheKey}); } } else { //沒有的話就將請求加入緩存隊列mCacheQueue,同時加入mWaitingRequests中用來作下次一樣請求來時的重複判斷依據 this.mWaitingRequests.put(cacheKey, (Object)null); this.mCacheQueue.add(request); } return request; } } }
經過判斷request.shouldCache(),來判斷是否能夠緩存,默認是能夠緩存的,若是不能緩存,則將請求添加到網絡請求隊列中,若是能緩存就判斷以前是否有執行相同的請求且尚未返回結果的,若是有的話將此請求加入mWaitingRequests隊列,再也不重複請求;沒有的話就將請求加入緩存隊列mCacheQueue,同時加入mWaitingRequests中用來作下次一樣請求來時的重複判斷依據。
從上面能夠看出RequestQueue的add()方法並無作什麼請求網絡或者對緩存進行操做。當將請求添加到網絡請求隊列或者緩存隊列時,這時在後臺的網絡調度線程和緩存調度線程輪詢各自的請求隊列發現有請求任務則開始執行,咱們先看看緩存調度線程。ui
CacheDispatcher的run()方法:this
public void run() { if(DEBUG) { VolleyLog.v("start new dispatcher", new Object[0]); } //線程優先級設置爲最高級別 Process.setThreadPriority(10); this.mCache.initialize(); while(true) { while(true) { while(true) { while(true) { try { //獲取緩存隊列中的一個請求 final Request e = (Request)this.mCacheQueue.take(); e.addMarker("cache-queue-take"); //若是請求取消了則將請求中止掉 if(e.isCanceled()) { e.finish("cache-discard-canceled"); } else { //查看是否有緩存的響應 Entry entry = this.mCache.get(e.getCacheKey()); //若是緩存響應爲空,則將請求加入網絡請求隊列 if(entry == null) { e.addMarker("cache-miss"); this.mNetworkQueue.put(e); //判斷緩存響應是否過時 } else if(!entry.isExpired()) { e.addMarker("cache-hit"); //對數據進行解析並回調給主線程 Response response = e.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders)); e.addMarker("cache-hit-parsed"); if(!entry.refreshNeeded()) { this.mDelivery.postResponse(e, response); } else { e.addMarker("cache-hit-refresh-needed"); e.setCacheEntry(entry); response.intermediate = true; this.mDelivery.postResponse(e, response, new Runnable() { public void run() { try { CacheDispatcher.this.mNetworkQueue.put(e); } catch (InterruptedException var2) { ; } } }); } } else { e.addMarker("cache-hit-expired"); e.setCacheEntry(entry); this.mNetworkQueue.put(e); } } } catch (InterruptedException var4) { if(this.mQuit) { return; } } } } } } } static { DEBUG = VolleyLog.DEBUG; }
看到四個while循環有些暈吧,讓咱們挑重點的說,首先從緩存隊列取出請求,判斷是否請求是否被取消了,若是沒有則判斷該請求是否有緩存的響應,若是有而且沒有過時則對緩存響應進行解析並回調給主線程。接下來看看網絡調度線程。url
NetworkDispatcher的run()方法:spa
public void run() { Process.setThreadPriority(10); while(true) { long startTimeMs; Request request; while(true) { startTimeMs = SystemClock.elapsedRealtime(); try { //從隊列中取出請求 request = (Request)this.mQueue.take(); break; } catch (InterruptedException var6) { if(this.mQuit) { return; } } } try { request.addMarker("network-queue-take"); if(request.isCanceled()) { request.finish("network-discard-cancelled"); } else { this.addTrafficStatsTag(request); //請求網絡 NetworkResponse e = this.mNetwork.performRequest(request); request.addMarker("network-http-complete"); if(e.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); } else { Response volleyError1 = request.parseNetworkResponse(e); request.addMarker("network-parse-complete"); if(request.shouldCache() && volleyError1.cacheEntry != null) { //將響應結果存入緩存 this.mCache.put(request.getCacheKey(), volleyError1.cacheEntry); request.addMarker("network-cache-written"); } request.markDelivered(); this.mDelivery.postResponse(request, volleyError1); } } } catch (VolleyError var7) { var7.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); this.parseAndDeliverNetworkError(request, var7); } catch (Exception var8) { VolleyLog.e(var8, "Unhandled exception %s", new Object[]{var8.toString()}); VolleyError volleyError = new VolleyError(var8); volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); this.mDelivery.postError(request, volleyError); } } }
網絡調度線程也是從隊列中取出請求而且判斷是否被取消了,若是沒取消就去請求網絡獲得響應並回調給主線程。請求網絡時調用this.mNetwork.performRequest(request),這個mNetwork是一個接口,實現它的類是BasicNetwork,咱們來看看BasicNetwork的performRequest()方法:
public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while(true) { HttpResponse httpResponse = null; Object responseContents = null; Map responseHeaders = Collections.emptyMap(); try { HashMap e = new HashMap(); this.addCacheHeaders(e, request.getCacheEntry()); httpResponse = this.mHttpStack.performRequest(request, e); StatusLine statusCode1 = httpResponse.getStatusLine(); int networkResponse1 = statusCode1.getStatusCode(); responseHeaders = convertHeaders(httpResponse.getAllHeaders()); if(networkResponse1 == 304) { Entry requestLifetime2 = request.getCacheEntry(); if(requestLifetime2 == null) { return new NetworkResponse(304, (byte[])null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } requestLifetime2.responseHeaders.putAll(responseHeaders); return new NetworkResponse(304, requestLifetime2.data, requestLifetime2.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } ...省略
從上面能夠看到在12行調用的是HttpStack的performRequest()方法請求網絡,接下來根據不一樣的響應狀態碼來返回不一樣的NetworkResponse。另外HttpStack也是一個接口,實現它的兩個類咱們在前面已經提到了就是HurlStack和HttpClientStack。讓咱們再回到NetworkDispatcher,請求網絡後,會將響應結果存在緩存中,若是響應結果成功則調用this.mDelivery.postResponse(request, volleyError1)來回調給主線程。來看看Delivery的postResponse()方法:
public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); this.mResponsePoster.execute(new ExecutorDelivery.ResponseDeliveryRunnable(request, response, runnable)); }
來看看ResponseDeliveryRunnable裏面作了什麼:
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) { this.mRequest = request; this.mResponse = response; this.mRunnable = runnable; } public void run() { if(this.mRequest.isCanceled()) { this.mRequest.finish("canceled-at-delivery"); } else { if(this.mResponse.isSuccess()) { this.mRequest.deliverResponse(this.mResponse.result); } else { this.mRequest.deliverError(this.mResponse.error); } if(this.mResponse.intermediate) { this.mRequest.addMarker("intermediate-response"); } else { this.mRequest.finish("done"); } if(this.mRunnable != null) { this.mRunnable.run(); } } } }
第17行調用了this.mRequest.deliverResponse(this.mResponse.result),這個就是實現Request<String>抽象類必需要實現的方法,咱們來看看StringRequest的源碼:
public class StringRequest extends Request<String> { private final Listener<String> mListener; public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); this.mListener = listener; } public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(0, url, listener, errorListener); } protected void deliverResponse(String response) { this.mListener.onResponse(response); } ...省略 }
在deliverResponse方法中調用了this.mListener.onResponse(response),最終將response回調給了Response.Listener的onResponse()方法。咱們用StringRequest請求網絡的寫法是這樣的:
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext()); StringRequest mStringRequest = new StringRequest(Request.Method.GET, "http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.i("wangshu", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("wangshu", error.getMessage(), error); } }); //將請求添加在請求隊列中 mQueue.add(mStringRequest);
看到第5行整個Volley的大體流程都通了吧,好了關於Volley的源碼就講到這裏。