最近有點對源碼上癮。。。有點時間,都歸納一些,總結下
Volley使用方法,不寫了,百度一堆。下包,依賴,使用
簡單代碼:
public void getVolley(View view) {
//第一步
RequestQueue requestQueue = Volley.newRequestQueue(this);
//第二步
StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() {
@Override
public void onResponse(String s) {
Log.e("TAG", "success : " + s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.e("TAG", "fail : " + volleyError.toString());
}
});
//第三步
requestQueue.add(stringRequest);
}
首先第一步,需要獲取到一個RequestQueue對象
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, (HttpStack)null);
}
方法一個個追,沒啥解釋~
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
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 var6) {
;
}
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 = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
關鍵代碼:
if(stack == null) {
if(VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
追進去看,可以發現,stack就是Volley對HttpClient和 HttpURLConnection 做的封裝。
都會創建一個Network,根據stack來處理網絡請求。
Network network = new BasicNetwork((HttpStack)stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
創建Network後,new 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:緩存分發器
public class CacheDispatcher extends Thread
其實就是開啓子線程的緩存請求隊列。
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();
}
同理,可以理解就是開啓子線程網絡請求隊列。
public class NetworkDispatcher extends Thread
整體框架基本就出來了,volley網絡請求首先從緩存中讀取是否有一份數據,如果有,緩存中讀取,加快了讀取速度。如果沒有,走NetworkDispatcher網絡讀取數據。
現在來單獨看看兩個類,緩存以及網絡
CacheDispatcher
public class CacheDispatcher extends Thread {
private static final boolean DEBUG;
private final BlockingQueue<Request<?>> mCacheQueue;
private final BlockingQueue<Request<?>> mNetworkQueue;
private final Cache mCache;
private final ResponseDelivery mDelivery;
private volatile boolean mQuit = false;
public CacheDispatcher(BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue, Cache cache, ResponseDelivery delivery) {
this.mCacheQueue = cacheQueue;
this.mNetworkQueue = networkQueue;
this.mCache = cache;
this.mDelivery = delivery;
}
public void quit() {
this.mQuit = true;
this.interrupt();
}
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<?> request = (Request)this.mCacheQueue.take();
request.addMarker("cache-queue-take");
if(request.isCanceled()) {
request.finish("cache-discard-canceled");
} else {
Entry entry = this.mCache.get(request.getCacheKey());
if(entry == null) {
request.addMarker("cache-miss");
this.mNetworkQueue.put(request);
} else if(!entry.isExpired()) {
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
if(!entry.refreshNeeded()) {
this.mDelivery.postResponse(request, response);
} else {
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 {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
this.mNetworkQueue.put(request);
}
}
} catch (InterruptedException var4) {
if(this.mQuit) {
return;
}
}
}
}
}
}
}
static {
DEBUG = VolleyLog.DEBUG;
}
}
注意,Thread 直接看run方法
一直while循環:
Entry entry = this.mCache.get(request.getCacheKey());
緩存隊列中獲取緩存數據,判斷是否爲空,爲空,添加到網絡請求隊列。
不爲空:entry.isExpired()判斷是否過期,過期,添加到網絡請求隊列,
不過期:
Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
解析數據:entry.refreshNeeded(),判斷是否需要刷新,需要刷新,添加到網絡請求隊列,不需要直接把結果回調出來。
完畢。
NetworkDispatcher.java
public class NetworkDispatcher extends Thread {
private final BlockingQueue<Request<?>> mQueue;
private final Network mNetwork;
private final Cache mCache;
private final ResponseDelivery mDelivery;
private volatile boolean mQuit = false;
public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {
this.mQueue = queue;
this.mNetwork = network;
this.mCache = cache;
this.mDelivery = delivery;
}
public void quit() {
this.mQuit = true;
this.interrupt();
}
@TargetApi(14)
private void addTrafficStatsTag(Request<?> request) {
if(VERSION.SDK_INT >= 14) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
}
public void run() {
Process.setThreadPriority(10);
while(true) {
Request request;
while(true) {
try {
request = (Request)this.mQueue.take();
break;
} catch (InterruptedException var4) {
if(this.mQuit) {
return;
}
}
}
try {
request.addMarker("network-queue-take");
if(request.isCanceled()) {
request.finish("network-discard-cancelled");
} else {
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 var5) {
this.parseAndDeliverNetworkError(request, var5);
} catch (Exception var6) {
VolleyLog.e(var6, "Unhandled exception %s", new Object[]{var6.toString()});
this.mDelivery.postError(request, new VolleyError(var6));
}
}
}
private void parseAndDeliverNetworkError(Request<?> request, VolleyError error) {
error = request.parseNetworkError(error);
this.mDelivery.postError(request, error);
}
}
run方法:繼續while循環,網絡請求不斷運行
NetworkResponse networkResponse = this.mNetwork.performRequest(request);
網絡請求,performRequest發送請求。
Response<?> response = request.parseNetworkResponse(networkResponse);
parseNetwordResponse解析數據
if(request.shouldCache() && response.cacheEntry != null) {
this.mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
這裏可以看到,解析的數據會存一份到緩存當中。
數據都處理完,給ResponseDelivery ,它給處理
public interface ResponseDelivery {
void postResponse(Request<?> var1, Response<?> var2);
void postResponse(Request<?> var1, Response<?> var2, Runnable var3);
void postError(Request<?> var1, VolleyError var2);
}
第二步:StringRequest 網絡成功失敗的回調
第三步add
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();
if(this.mWaitingRequests.containsKey(cacheKey)) {
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 {
this.mWaitingRequests.put(cacheKey, (Object)null);
this.mCacheQueue.add(request);
}
return request;
}
}
}
消息添加到隊列中,關鍵代碼:
!request.shouldCache()
進行判斷,當前請求是否可以緩存。如果不可以緩存,添加到網絡請求隊列,可以緩存,就添加到緩存請求隊列。
總結:volley發送網絡請求,開啓兩個請求隊列,一個緩存請求隊列,一個網絡請求隊列。先從緩存請求隊列去檢查是否過期,數據是否需要刷新呀,如果過期或者需要刷新,添加到網絡隊列進行網絡請求,NetworkDispatcher處理,交給主線程迴應。