在使用Volley进行网络请求时,我们只需要调用一句mVolleyRequestQueue.add(mRequest);就可以开始网络请求了,这个过程是怎么样的呢,来看一下源码:
public <T> Request<T> add(Request<T> request) {
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);//这个mCurrentRequests是一个HashSet
}
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
if (!request.shouldCache()) {
mNetworkQueue.add(request);//这个mNetworkQueue是一个PriorityBlockingQueue<Request<?>>
return request;
}
/*以下是有缓存的情况,先省略不写*/
}
可以看到,RequestQueue类里有一个HashSet:mCurrentRequests,和一个 PriorityBlockingQueue:mNetworkQueue
在add请求时,把这个请求添加到了这个set和mNetworkQueue中去了
到这里,消息已经添加到请求队列中去了。
用Volley.newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes)创建RequestQueue实例时:
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {//这句在api 9及以上都用,因此基本上stack 就是 HurlStack ,这个是最终进行网络请求的类,后面再说
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue;
queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);//这个方法最终会调用RequestQueue(Cache cache, Network network, int threadPoolSize,ResponseDelivery delivery)
queue.start();
return queue;
}
在这里通过start启动了queue
看一下RequestQueue(Cache cache, Network network, int threadPoolSize,ResponseDelivery delivery):
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}
可以看到,RequestQueue最终维护了一个NetworkDispatcher数组,这个数组的长度默认为4,从命名可以看出,这是这个队列维护的线程数,第二个参数实际上是Volley利用stack参数给RequestQueue提供的一个Network network = new BasicNetwork(stack),
来看queue的start方法
public void start() {
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
实际上是启动了N个NetworkDispatcher,这个类继承了Thread类,NetworkDispatcher最终调用本地方法nativeCreate(this, stackSize, daemon)这个看不懂,但是NetworkDispatcher有个run方法,最终应该是调用run,来看一下源码,实际上是一个死循环,不断从取消息,如有则使用mNetwork.performRequest来进行请求
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Request<?> request;
while (true) {
request = null;
request = mQueue.take();
NetworkResponse networkResponse = mNetwork.performRequest(request);
}
}
调用了mNetwork的performRequest,就是前面提供的BasicNetwork
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
//前面提到,这个stack实际上是一个HurlStack()
httpResponse = mHttpStack.performRequest(request, headers);
}
HurlStack()中的performRequest:
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
String url = request.getUrl();
HashMap<String, String> map = new HashMap<String, String>();
map.putAll(request.getHeaders());
map.putAll(additionalHeaders);
if (mUrlRewriter != null) {
String rewritten = mUrlRewriter.rewriteUrl(url);
if (rewritten == null) {
throw new IOException("URL blocked by rewriter: " + url);
}
url = rewritten;
}
URL parsedUrl = new URL(url);
HttpURLConnection connection = openConnection(parsedUrl, request);
for (String headerName : map.keySet()) {
connection.addRequestProperty(headerName, map.get(headerName));
}
setConnectionParametersForRequest(connection, request);
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
int responseCode = connection.getResponseCode();
if (responseCode == -1) {
throw new IOException("Could not retrieve response code from HttpUrlConnection.");
}
StatusLine responseStatus = new BasicStatusLine(protocolVersion,
connection.getResponseCode(), connection.getResponseMessage());
BasicHttpResponse response = new BasicHttpResponse(responseStatus);
if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) {
response.setEntity(entityFromConnection(connection));
}
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
if (header.getKey() != null) {
Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
response.addHeader(h);
}
}
return response;
}
可以看到,最终是用HttpUrlConnection进行了网络请求。