解析Android框架之Volley源碼
Volley簡單使用
我這里是以依賴架包的形式 ,大家也可以以gradle的形式進行依賴。
好了,接下來上代碼了.....
//獲取volley的請求對象 RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext()); StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, "http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String s) { Log.d("MainActivity", "----->" + s); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Log.d("MainActivity", "---volleyError-->" + volleyError); } }); requestQueue.add(stringRequest);
從代碼可以看出,首先newRequestQueue來獲取到一個請求隊列,然后在將StringRequest這個請求添加到請求隊列中,就可以了,就是這么簡單。當然請求不值StringRequest,還有JsonObjectRequest ,ImageRequest等等但是用法都是一樣的,這里就不貼代碼了。Volley的簡單使用就這樣可以進行請求了。是不是很簡單
Volley執(zhí)行原理
但是這個不是本篇的重點,重點是分析一下這些是怎么執(zhí)行的。先上一張圖
我們先看看newRequestQueue這個內(nèi)部是怎么執(zhí)行的,代碼一開始連續(xù)執(zhí)行了幾個重載方法,最后走到newRequestQueue
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { File cacheDir = new File(context.getCacheDir(), "volley"); String userAgent = "volley/0"; try { String packageName = context.getPackageName(); PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); userAgent = packageName + "/" + info.versionCode; } catch (NameNotFoundException var7) { ; } //這里進行了一個版本的判斷 2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection if (stack == null) { if (VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } Network network = new BasicNetwork((HttpStack)stack); RequestQueue queue; if (maxDiskCacheBytes <= -1) { queue = new RequestQueue(new DiskBasedCache(cacheDir), network); } else { queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network); } queue.start(); return queue; }
在這里,我們看到了一個版本判斷,是不是瞬間感覺有點熟悉,沒錯,我們前面說的,volley2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection就是在這里進行判斷的。接著看queue.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(); } }
mCacheDispatcher是緩存調(diào)度線程,NetworkDispatcher是網(wǎng)絡調(diào)度線程,而這個this.mDispatchers.length系統(tǒng)默認的大小為4,也就是說,在這里總共啟動了5個線程在后臺運行。
好了,到這里,就可以了,看源碼不要每一行都弄懂,不然,出不來了。到這里就拿到了這個RequestQueue對象?;剡^頭來看前面使用的代碼
//獲取volley的請求對象 RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext()); StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, "http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String s) { Log.d("MainActivity", "----->" + s); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Log.d("MainActivity", "---volleyError-->" + volleyError); } }); requestQueue.add(stringRequest);
我們拿到這個RequestQueue對象以后,然后就把這個請求通過add方法添加到隊列中,我們看看這個add()方法是怎么執(zhí)行的。
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 var7 = this.mWaitingRequests; synchronized(this.mWaitingRequests) { String cacheKey = request.getCacheKey(); if (this.mWaitingRequests.containsKey(cacheKey)) { //判斷之前是否執(zhí)行過,但是還沒有返回結果 Queue<Request<?>> 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中用來做下次同樣請求來時的重復判斷依據(jù) this.mWaitingRequests.put(cacheKey, (Object)null); this.mCacheQueue.add(request); } return request; } } }
從代碼中可以看出,首先判斷是否可以緩存,當然,默認是可以緩存的。如果不能緩存的話,則通過this.mNetworkQueue.add(request);將請求添加到網(wǎng)絡請求隊列中。如果可以緩存,則還會判斷一次這個請求是否請求,如果執(zhí)行過就就通過this.mWaitingRequests.put(cacheKey, stagedRequests);添加到mWaitingRequests隊列,不在重復請求。否則就加入到緩存隊列。
大體的流程是這樣?,F(xiàn)在我們看看緩存的,和網(wǎng)絡的是怎么執(zhí)行的。我們找到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,找到run()方法
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 { while(true) { final Request<?> request = (Request)this.mCacheQueue.take(); //從緩存隊列中獲取到一個請求 request.addMarker("cache-queue-take"); if (request.isCanceled()) { //判斷請求是否取消,如果取消了,那就將該請求finish掉 request.finish("cache-discard-canceled"); } else { Entry entry = this.mCache.get(request.getCacheKey()); if (entry == null) {//如果從緩存中取出來的內(nèi)容為空,則將請求加入到網(wǎng)絡線程中再次請求 request.addMarker("cache-miss"); this.mNetworkQueue.put(request); } else if (entry.isExpired()) { //如果請求過期了,則將請求加入到網(wǎng)絡線程中再次請求 request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); this.mNetworkQueue.put(request); } else { //將數(shù)據(jù)回調(diào)到主線程 request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); if (entry.refreshNeeded()) { request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); response.intermediate = true; this.mDelivery.postResponse(request, response, new Runnable() { public void run() { try { CacheDispatcher.this.mNetworkQueue.put(request); } catch (InterruptedException var2) { ; } } }); } else { this.mDelivery.postResponse(request, response); } } } } } catch (InterruptedException var4) { if (this.mQuit) { return; } } } } } } }
這里嵌套了幾個循環(huán),有點凌亂啊,但是慢慢分析的話,就會發(fā)現(xiàn),其實很清晰。我在注釋上面寫了,這里就不重復了
我們在看看NetworkDispatcher,看看網(wǎng)絡線程是怎么執(zhí)行的。一樣找到run()方法
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()) { //如果請求取消了,則將請求finish掉 request.finish("network-discard-cancelled"); } else {//進行網(wǎng)絡請求 this.addTrafficStatsTag(request); NetworkResponse networkResponse = this.mNetwork.performRequest(request); request.addMarker("network-http-complete"); if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); } else { Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete"); if (request.shouldCache() && response.cacheEntry != null) { this.mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } request.markDelivered(); this.mDelivery.postResponse(request, response); } } } 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); } } }
代碼比較多,我們直接找到NetworkResponse networkResponse = this.mNetwork.performRequest(request);這句代碼,這句代碼就是請求網(wǎng)絡的代碼,最核心的。performRequest是一個接口,我們看看這個performRequest()方法。Network在最開始說版本判斷的時候里面有一句代碼Network network = new BasicNetwork((HttpStack)stack); 從這句代碼,我們可以知道BasicNetwork才是最終實現(xiàn)網(wǎng)絡請求的類,我們找到performRequest方法
public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while(true) { HttpResponse httpResponse = null; byte[] responseContents = null; Map responseHeaders = Collections.emptyMap(); try { Map<String, String> headers = new HashMap(); this.addCacheHeaders(headers, request.getCacheEntry()); httpResponse = this.mHttpStack.performRequest(request, headers); StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode(); responseHeaders = convertHeaders(httpResponse.getAllHeaders()); if (statusCode == 304) { Entry entry = request.getCacheEntry(); if (entry == null) { return new NetworkResponse(304, (byte[])null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } entry.responseHeaders.putAll(responseHeaders); return new NetworkResponse(304, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } if (statusCode == 301 || statusCode == 302) { String newUrl = (String)responseHeaders.get("Location"); request.setRedirectUrl(newUrl); } byte[] responseContents; if (httpResponse.getEntity() != null) { responseContents = this.entityToBytes(httpResponse.getEntity()); } else { responseContents = new byte[0]; } long requestLifetime = SystemClock.elapsedRealtime() - requestStart; this.logSlowRequests(requestLifetime, request, responseContents, statusLine); if (statusCode >= 200 && statusCode <= 299) { return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); } throw new IOException(); } catch (SocketTimeoutException var12) { attemptRetryOnException("socket", request, new TimeoutError()); } catch (ConnectTimeoutException var13) { attemptRetryOnException("connection", request, new TimeoutError()); } catch (MalformedURLException var14) { throw new RuntimeException("Bad URL " + request.getUrl(), var14); } catch (IOException var15) { int statusCode = false; NetworkResponse networkResponse = null; if (httpResponse == null) { throw new NoConnectionError(var15); } int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != 301 && statusCode != 302) { VolleyLog.e("Unexpected response code %d for %s", new Object[]{statusCode, request.getUrl()}); } else { VolleyLog.e("Request at %s has been redirected to %s", new Object[]{request.getOriginUrl(), request.getUrl()}); } if (responseContents == null) { throw new NetworkError(networkResponse); } networkResponse = new NetworkResponse(statusCode, (byte[])responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); if (statusCode != 401 && statusCode != 403) { if (statusCode != 301 && statusCode != 302) { throw new ServerError(networkResponse); } attemptRetryOnException("redirect", request, new AuthFailureError(networkResponse)); } else { attemptRetryOnException("auth", request, new AuthFailureError(networkResponse)); } } } }
代碼比較多,但是大多數(shù)代碼是判斷狀態(tài)返回碼的,不需要理會。
我們直接看httpResponse = this.mHttpStack.performRequest(request, headers);這一句代碼,HttpStack這個有沒有很熟悉。沒有??沒關系我在復制一次代碼
if (stack == null) { if (VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } }
還是在這個版本判斷這里,這里就是HurlStack就是真正的網(wǎng)絡請求的類了,網(wǎng)絡請求,就是寫在這個類里面的。好了,volley整個流程大概就是這樣了?,F(xiàn)在大家回過頭看最初的哪一張圖,是不是明了很多。
以上就是解析Android框架之Volley源碼的詳細內(nèi)容,更多關于Android框架之Volley源碼的資料請關注腳本之家其它相關文章!
相關文章
Android fragment實現(xiàn)按鈕點擊事件的示例講解
下面小編就為大家分享一篇Android fragment實現(xiàn)按鈕點擊事件的示例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android利用SurfaceView實現(xiàn)簡單計時器
這篇文章主要為大家詳細介紹了Android利用SurfaceView實現(xiàn)一個簡單計時器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01Android App中使用Gallery制作幻燈片播放效果
這篇文章主要介紹了Android App中使用Gallery制作幻燈片播放效果,相冊應用中的輪播功能也與本文中例子的原理類似,需要的朋友可以參考下2016-04-04Android的Fragment的生命周期各狀態(tài)和回調(diào)函數(shù)使用
這篇文章主要介紹了Android的Fragments的生命周期各狀態(tài)和回調(diào)函數(shù)使用,Fragments的生命周期與Activity息息相關,需要的朋友可以參考下2016-02-02Android從系統(tǒng)Gallery獲取圖片具體實現(xiàn)
這篇文章主要介紹了Android從系統(tǒng)Gallery獲取圖片具體實現(xiàn),有需要的朋友可以參考一下2013-12-12