一直看源码也是记不住,总是忘记,希望通过博客可以给自己留存一些记忆。
我从入口开始分析,创建一个请求队列,通过Volley的静态方法newRequestQueue新建,然后将请求添加至请求队列即可。
RequestQueue mRequestQueue = Volley.newRequestQueue(context);
mRequestQueue.add(request);
可以通过mRequestQueue的cancelAll方法取消所有TAG请求。
@Override
protected void onDestroy() {
super.onDestroy();
mRequestQueue.cancelAll(TAG);
}
接着用一个最简单的请求方式,作为示例看一下请求的参数
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// TODO
Log.e(TAG, response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO
error.printStackTrace();
}
});
第一个参数,是一个请求方式,一共有GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH八种方式。
第二个参数,是请求的网络地址url。
第三个参数,是请求返回的响应结果的回调。
第四个参数,是请求返回的错误响应的回调。
以上是一个大概的使用过程,通过这个过程进行分析。
首先,请求队列的创建调用了Volley的newRequestQueue静态方法,跟进去之后发现最终调用了一个含有多个参数的newRequestQueue静态方法。
RequestQueue queue = new RequestQueue(cache==null?new DiskBasedCache(cacheDir):cache, network);
queue.start();
这个方法里new出一个请求队列,请求队列的构造方法需要两个参数,一个缓存,一个网络任务。构造方法没什么说可说的了,就是初始化一些成员变量。创建队列的目的是为了处理请求,所以调用了start方法。
/**
* Starts the dispatchers in this queue.
*/
public void start() {
stop(); // Make sure any currently running dispatchers are stopped.
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
start方法里很简单,是新建了一个调度缓存的线程和一个调度网络任务的线程数组,并将所有线程调用start方法启动。接下来,就要去看看线程里的run方法了。
先看看CacheDispatcher的run方法,去除掉我认为不影响流程的代码,剩余的部分就是说,不断的从缓存队列里取任务请求。如果缓存中没有或者已经过期了,就将请求添加至网络请求队列。最后如果缓存中存在的话,就去处理响应结果并解析。
@Override
public void run() {
······
while (true) {
// Get a request from the cache triage queue, blocking until
// at least one is available.
final Request<?> request = mCacheQueue.take();
request.addMarker("cache-queue-take");
···
// Attempt to retrieve this item from cache.
Cache.Entry entry = mCache.get(request.getCacheKey());
if (entry == null) {
request.addMarker("cache-miss");
// Cache miss; send off to the network dispatcher.
mNetworkQueue.put(request);
continue;
}
// If it is completely expired, just send it to the network.
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
// We have a cache hit; parse its data for delivery back to the request.
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
···
}
}
再看看NetworkDispatcher的run方法,也是有个while死循环,不断的从请求队列里取任务请求。然后通过Network的performRequest方法处理请求,返回响应结果。然后对响应结果进行解析,最后,判断一下是否添加至缓存中,若条件满足,则将请求添加至缓存,方便下次进行快速读取。
@Override
public void run() {
while (true) {
Request<?> request;
// Take a request from the queue.
request = mQueue.take();
······
// Perform the network request.
NetworkResponse networkResponse = mNetwork.performRequest(request);
request.addMarker("network-http-complete");
······
// Parse the response here on the worker thread.
Response<?> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");
// Write to cache if applicable.
// TODO: Only update cache metadata instead of entire record for 304s.
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
···
}
}
若问请求哪里来?答:通过请求队列的add方法添加。就是最前面提到的mRequestQueue.add(request);
以上就是Volley源码阅读的大概一个过程,无需在意太多的细节,这是我总结出的阅读源码的经验。当然,经验有限,目前也只能写成这样。
在前进的道路上,跟随一些大神的脚步是必不可免的。为了加强理解,更多细节可以看看Volley源码解析