解析Android框架之Volley源碼
Volley簡單使用
我這里是以依賴架包的形式 ,大家也可以以gradle的形式進(jìn)行依賴。

好了,接下來上代碼了.....
//獲取volley的請(qǐng)求對(duì)象
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來獲取到一個(gè)請(qǐng)求隊(duì)列,然后在將StringRequest這個(gè)請(qǐng)求添加到請(qǐng)求隊(duì)列中,就可以了,就是這么簡單。當(dāng)然請(qǐng)求不值StringRequest,還有JsonObjectRequest ,ImageRequest等等但是用法都是一樣的,這里就不貼代碼了。Volley的簡單使用就這樣可以進(jìn)行請(qǐng)求了。是不是很簡單
Volley執(zhí)行原理
但是這個(gè)不是本篇的重點(diǎn),重點(diǎn)是分析一下這些是怎么執(zhí)行的。先上一張圖

我們先看看newRequestQueue這個(gè)內(nèi)部是怎么執(zhí)行的,代碼一開始連續(xù)執(zhí)行了幾個(gè)重載方法,最后走到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) {
;
}
//這里進(jìn)行了一個(gè)版本的判斷 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;
}
在這里,我們看到了一個(gè)版本判斷,是不是瞬間感覺有點(diǎn)熟悉,沒錯(cuò),我們前面說的,volley2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection就是在這里進(jìn)行判斷的。接著看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)絡(luò)調(diào)度線程,而這個(gè)this.mDispatchers.length系統(tǒng)默認(rèn)的大小為4,也就是說,在這里總共啟動(dòng)了5個(gè)線程在后臺(tái)運(yùn)行。
好了,到這里,就可以了,看源碼不要每一行都弄懂,不然,出不來了。到這里就拿到了這個(gè)RequestQueue對(duì)象?;剡^頭來看前面使用的代碼
//獲取volley的請(qǐng)求對(duì)象
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);
我們拿到這個(gè)RequestQueue對(duì)象以后,然后就把這個(gè)請(qǐng)求通過add方法添加到隊(duì)列中,我們看看這個(gè)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í)行過,但是還沒有返回結(jié)果
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 {
//沒有的話就將請(qǐng)求加入緩存隊(duì)列mCacheQueue,同時(shí)加入mWaitingRequests中用來做下次同樣請(qǐng)求來時(shí)的重復(fù)判斷依據(jù)
this.mWaitingRequests.put(cacheKey, (Object)null);
this.mCacheQueue.add(request);
}
return request;
}
}
}
從代碼中可以看出,首先判斷是否可以緩存,當(dāng)然,默認(rèn)是可以緩存的。如果不能緩存的話,則通過this.mNetworkQueue.add(request);將請(qǐng)求添加到網(wǎng)絡(luò)請(qǐng)求隊(duì)列中。如果可以緩存,則還會(huì)判斷一次這個(gè)請(qǐng)求是否請(qǐng)求,如果執(zhí)行過就就通過this.mWaitingRequests.put(cacheKey, stagedRequests);添加到mWaitingRequests隊(duì)列,不在重復(fù)請(qǐng)求。否則就加入到緩存隊(duì)列。
大體的流程是這樣?,F(xiàn)在我們看看緩存的,和網(wǎng)絡(luò)的是怎么執(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(); //從緩存隊(duì)列中獲取到一個(gè)請(qǐng)求
request.addMarker("cache-queue-take");
if (request.isCanceled()) { //判斷請(qǐng)求是否取消,如果取消了,那就將該請(qǐng)求finish掉
request.finish("cache-discard-canceled");
} else {
Entry entry = this.mCache.get(request.getCacheKey());
if (entry == null) {//如果從緩存中取出來的內(nèi)容為空,則將請(qǐng)求加入到網(wǎng)絡(luò)線程中再次請(qǐng)求
request.addMarker("cache-miss");
this.mNetworkQueue.put(request);
} else if (entry.isExpired()) { //如果請(qǐng)求過期了,則將請(qǐng)求加入到網(wǎng)絡(luò)線程中再次請(qǐ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;
}
}
}
}
}
}
}
這里嵌套了幾個(gè)循環(huán),有點(diǎn)凌亂啊,但是慢慢分析的話,就會(huì)發(fā)現(xiàn),其實(shí)很清晰。我在注釋上面寫了,這里就不重復(fù)了
我們?cè)诳纯碞etworkDispatcher,看看網(wǎng)絡(luò)線程是怎么執(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(); //獲取到一個(gè)請(qǐng)求
break;
} catch (InterruptedException var6) {
if (this.mQuit) {
return;
}
}
}
try {
request.addMarker("network-queue-take");
if (request.isCanceled()) { //如果請(qǐng)求取消了,則將請(qǐng)求finish掉
request.finish("network-discard-cancelled");
} else {//進(jìn)行網(wǎng)絡(luò)請(qǐ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);這句代碼,這句代碼就是請(qǐng)求網(wǎng)絡(luò)的代碼,最核心的。performRequest是一個(gè)接口,我們看看這個(gè)performRequest()方法。Network在最開始說版本判斷的時(shí)候里面有一句代碼Network network = new BasicNetwork((HttpStack)stack); 從這句代碼,我們可以知道BasicNetwork才是最終實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐ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)返回碼的,不需要理會(huì)。
我們直接看httpResponse = this.mHttpStack.performRequest(request, headers);這一句代碼,HttpStack這個(gè)有沒有很熟悉。沒有??沒關(guān)系我在復(fù)制一次代碼
if (stack == null) {
if (VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
還是在這個(gè)版本判斷這里,這里就是HurlStack就是真正的網(wǎng)絡(luò)請(qǐng)求的類了,網(wǎng)絡(luò)請(qǐng)求,就是寫在這個(gè)類里面的。好了,volley整個(gè)流程大概就是這樣了?,F(xiàn)在大家回過頭看最初的哪一張圖,是不是明了很多。
以上就是解析Android框架之Volley源碼的詳細(xì)內(nèi)容,更多關(guān)于Android框架之Volley源碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android fragment實(shí)現(xiàn)按鈕點(diǎn)擊事件的示例講解
下面小編就為大家分享一篇Android fragment實(shí)現(xiàn)按鈕點(diǎn)擊事件的示例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01
Android 判斷ip地址合法實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 判斷ip地址合法實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android利用SurfaceView實(shí)現(xiàn)簡單計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了Android利用SurfaceView實(shí)現(xiàn)一個(gè)簡單計(jì)時(shí)器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Flutter自定義實(shí)現(xiàn)彈出層的示例代碼
這篇文章主要為大家詳細(xì)介紹了Flutter如何自定義組件實(shí)現(xiàn)彈出層的效果,?文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-08-08
Android App中使用Gallery制作幻燈片播放效果
這篇文章主要介紹了Android App中使用Gallery制作幻燈片播放效果,相冊(cè)應(yīng)用中的輪播功能也與本文中例子的原理類似,需要的朋友可以參考下2016-04-04
Android的Fragment的生命周期各狀態(tài)和回調(diào)函數(shù)使用
這篇文章主要介紹了Android的Fragments的生命周期各狀態(tài)和回調(diào)函數(shù)使用,Fragments的生命周期與Activity息息相關(guān),需要的朋友可以參考下2016-02-02
Android從系統(tǒng)Gallery獲取圖片具體實(shí)現(xiàn)
這篇文章主要介紹了Android從系統(tǒng)Gallery獲取圖片具體實(shí)現(xiàn),有需要的朋友可以參考一下2013-12-12

