寫在最前面的話:送給還在迷茫看不懂的童鞋,跟著我一步步看,小白也能看懂,從而對整體有一個把握,分析的開始以基本使用為切入點,一步步深入。
1. 建立獲取 RequestQueue
物件
RequestQueue mQueue = Volley.newRequestQueue(this);
複製程式碼
開始進入:::
Vollery # newRequestQueue()
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
.....
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 NoCache(), network);
queue.start();
return queue;
}
複製程式碼
看到我開始羅列程式碼了,不要慌,還好不長,在能力範圍內:
剛開始就根據不同的Android 系統版本,建立不同的物件,我們先可以大概瞭解一下 HurlStack
和 HttpClientStack
是啥?
HurlStack.java
public class HurlStack implements HttpStack {
....
public HttpResponse performRequest(Request<?> request,
Map<String, String> additionalHeaders) {
....
URL parsedUrl = new URL(url);
HttpURLConnection connection = this.openConnection(parsedUrl, request);
....
}
複製程式碼
HttpClientStack.java
public class HttpClientStack implements HttpStack {
protected final HttpClient mClient;
...
public HttpResponse performRequest(Request<?> request,
Map<String, String> additionalHeaders) {
....
return this.mClient.execute(httpRequest)
}
}
複製程式碼
HttpStack.java
public interface HttpStack {
HttpResponse performRequest(Request<?> var1, Map<String, String> var2) ;
}
複製程式碼
看到這裡我們大概明白了,原來是根據不同的系統版本,確定最終選擇進行的網路請求,那為什麼大於9 用 HttpUrlConnection
小於9用 HttpClient
呢?在這裡不過多介紹了,網上一搜就知道了。
Ok,那我們繼續向下走,回到上面的程式碼,為了方便檢視,我重新貼上一份程式碼下來:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
.....
if (stack == null) {
if (VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
//HttpStack 又一次被封裝為Network介面型別
Network network = new BasicNetwork((HttpStack)stack);
RequestQueue queue = new RequestQueue(new NoCache(), network);
queue.start();
return queue;
}
複製程式碼
Network.java
public interface Network {
NetworkResponse performRequest(Request<?> var1) throws VolleyError;
}
複製程式碼
哦 原來是介面,它的實現類 BasicNetwork
BasicNetwork.java
public class BasicNetwork implements Network {
//將網路請求的例項傳入,方便後面的呼叫
public BasicNetwork(HttpStack httpStack) {
this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
}
....
}
複製程式碼
目前而止,那麼它們之間的關係是啥樣的呢,我畫了一張圖:
很清晰吧,目前我們先不考慮這個BasicNetwork
類中幹了什麼,我們先根據程式碼的思路一步步向下走,保證我們整體主幹不變,避免陷入只見樹木不見森林的局勢。
Ok,我們再次回到原來的程式碼:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
.....
if (stack == null) {
if (VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
//HttpStack 又一次被封裝為Network介面型別,
//建立BasicNetwork呼叫了構造方法是一個引數的
Network network = new BasicNetwork((HttpStack)stack);
//到這裡了...........
//建立一個 請求佇列 RequestQueue,並且在建構函式中,傳入了兩個
//引數,好,我們接下來就要去RequestQueue.java類中看一眼了。
RequestQueue queue = new RequestQueue(new NoCache(), network);
queue.start();
return queue;
}
複製程式碼
RequestQueue.java
public RequestQueue(Cache cache, Network network) {
this(cache, network, 2);
}
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
this.mSequenceGenerator = new AtomicInteger();
this.mWaitingRequests = new HashMap();
this.mCurrentRequests = new HashSet();
this.mCacheQueue = new PriorityBlockingQueue();
this.mNetworkQueue = new PriorityBlockingQueue();
this.mCache = cache;
this.mNetwork = network;
this.mDispatchers = new NetworkDispatcher[threadPoolSize];
this.mDelivery = delivery;
}
複製程式碼
在構造方法中,傳入一個Cache
物件,network
物件,預設初始化一個threadPoolSize = 2
,還有一系列初始化操作.
Ok,再次返回我們之前的程式碼:
....
RequestQueue queue = new RequestQueue(new NoCache(), network);
queue.start();
複製程式碼
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()
方法。
接下來,我們就認識下 CacheDispatcher.java
類:
//原來它是一個執行緒
public class CacheDispatcher extends Thread {
//快取佇列,用BlockingQueue 管理儲存
private final BlockingQueue<Request<?>> mCacheQueue;
public CacheDispatcher(BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue, Cache cache, ResponseDelivery delivery) {
//引數賦值
this.mCacheQueue = cacheQueue;
this.mNetworkQueue = networkQueue;
this.mCache = cache;
this.mDelivery = delivery;
}
//呼叫start 方法必定呼叫run 方法
public void run() {
.....
Process.setThreadPriority(10);
//這裡初始化快取,還記得我們之前預設傳入了一個 NoCache 嗎?
//這裡Cache 是介面,子類有兩種NoCache 和 DiskBasedCache兩種
this.mCache.initialize();
//巢狀了好多迴圈啊......因為要不斷去讀取是否有任務嘛,沒有的時候就一直等待
while(true) {
while(true) {
while(true) {
while(true) {
try {
// 表示從快取佇列中取出一個 Request, 那第一次肯定沒有啊,就一直等待......
final Request<?> request = (Request)this.mCacheQueue.take();
.....這裡我先省略了,因為還沒真正到這一步
}
複製程式碼
OK,返回到我們之前的操作:
RequestQueue.java
private NetworkDispatcher[] mDispatchers ;
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 2;
public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
....
this.mDispatchers = new NetworkDispatcher[threadPoolSize];
....
}
public void start() {
this.stop();
this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
this.mCacheDispatcher.start();
//到這裡啦,
//從構造方法我們可以得知 mDispatchers.length = 2 ,上
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();
}
}
複製程式碼
迴圈遍歷生成2 個 NetworkDispatcher
物件,並將 NetworkDispatcher
物件儲存在一個 mDispatchers
的陣列中去了,最後呼叫了 start
方法。
Ok,那接下來我們就看下這個 NetworkDispatcher.java
類了。
NetworkDispatcher.java
public class NetworkDispatcher extends Thread {
// 網路請求佇列
private final BlockingQueue<Request<?>> mQueue;
//物件初始化
public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {
this.mQueue = queue;
this.mNetwork = network;
this.mCache = cache;
this.mDelivery = delivery;
}
//既然是執行緒,呼叫 start 方法,必定呼叫 run 方法
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;
}
}
}
.....底部程式碼我也省略了,因為都是獲取到請求之後所做的處理
複製程式碼
至此,對於RequestQueue
的初始化第一步我們完成了對它的瞭解,你明白了嗎? 下一篇我們針對 mQueue.add(request)
真正需要進行網路請求進行繼續分析。如果這篇文章有幫助到你,給個贊就是我最大的鼓勵了,比心?。