RequestQueue:表示请求队列,查看源码得知,里面包含一个CacheDispatcher(用于处理走缓存请求的调度线程)、NetworkDispatcher数组(用于处理走网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 函数启动时会启动CacheDispatcher和NetworkDispatchers。
本篇内容我们来详细的了解一下RequestQueue相关内容。
源码路径com.android.volley.RequestQueue
在使用Request时,首先需要创建一个请求队列RequestQueue,
RequestQueue queue = Volley.newRequestQueue(this);
//创建出请求队列后调用start开始启动队列
private static RequestQueue newRequestQueue(Context context, Network network) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
这个请求队列的构造比较简单,内部通过判断SDK的版本来进行判断来使用哪个网络请求方式,相关文章请查看《Android网络框架volley学习(三)底层网络请求分析》。我们进入到RequestQueue的内部详细看下源码。
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}
以上是它的构造函数,里面有四个参数,分别是:
另外还存在其他两个构造函数,不过最终都是调用的最基本的构造方法。
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
this(cache, network, threadPoolSize,
new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
public RequestQueue(Cache cache, Network network) {
this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);
}
默认情况下,请求队列RequestQueue是通过Volley工具类产生的即:
RequestQueue queue = Volley.newRequestQueue(this);
不过通过它的共有构造方法,我们可以生成自己的请求队列,即采用自定义的HttpStatck,采用自定义的Network实现,采用自定义的 Cache 实现等来构建RequestQueue。
请求队列RequestQueue构造后,我们会产生一个基本的请求,如 StringRequest、JsonObjectRequest、 JsonArrayRequest等或者自己实现的请求方式,最后将生成的网络请求添加到请求队列中,即
StringRequest mStringRequest=new StringRequest("url", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//将请求添加到请求队列中
queue.add(mStringRequest);
开始的时候我们构造出请求队列后,将会调用start方法,开启请求队列。
public void start() {
stop();
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
开启请求队列比较简单,主要就是缓存调度开启工作和网络调度开启工作。接着我们接着进入到add中去分析一下源码。
public <T> Request<T> add(Request<T> request) {
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);
}
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}
mCacheQueue.add(request);
return request;
}
对于add方法,将当前的请求添加到请求队列中,参数是Request,它是一个抽象类,需要我们自己实现,可以是StringRequest或者我们自己实现的请求。
在这里面维护了一个当前请求集合,当前请求队列处理的所有请求都将放入到该集合中去,后续的请求也将会放入到该集合中来。
/**
* The set of all requests currently being processed by this RequestQueue. A Request
* will be in this set if it is waiting in any queue or currently being processed by
* any dispatcher.
*/
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
放入到请求集合中后进行处理,首先判断是否需要放入到缓存队列中去,如果不需要的话则直接放到网络请求队列中去。
关于缓存队列和网络请求队列,我们下篇再进行详细分析。进过一系列的操作,一条请求就完成了。我们继续看RequestQueue中其他的方法。既然可以发起请求,当然也可以取消请求,取消当前的请求通过cancelAll(final Object tag) 方法来操作。
/**
* Cancels all requests in this queue with the given tag. Tag must be non-null
* and equality is by identity.
*/
public void cancelAll(final Object tag) {
if (tag == null) {
throw new IllegalArgumentException("Cannot cancelAll with a null tag");
}
cancelAll(new RequestFilter() {
@Override
public boolean apply(Request<?> request) {
return request.getTag() == tag;
}
});
}
对于请求的取消,主要是通过发起请求时设置的tag来判别是哪个请求需要取消。当一条请求完成后,我们需要将它从请求队列中移除掉。即在当前的集合中去掉该请求。
/**
* Called from {@link Request#finish(String)}, indicating that processing of the given request
* has finished.
*/
<T> void finish(Request<T> request) {
// Remove from the set of requests currently being processed.
synchronized (mCurrentRequests) {
mCurrentRequests.remove(request);
}
synchronized (mFinishedListeners) {
for (RequestFinishedListener<T> listener : mFinishedListeners) {
listener.onRequestFinished(request);
}
}
}
以上便是volley里面关于请求队列的一些信息。