Volley源码解析<四> RequestQueue请求队列
@[Volley, 核心, RequestQueue]
声明:转载请注明出处,知识有限,如有错误,请多多交流指正!
RequestQueue结构
RequestQueue类
1. 构造方法
RequestQueue是请求队列,负责分发请求,取缓存或读网络,所以其构造函数中需要一个Cache对象和一个Network对象,还有一个ResponseDelivery对象用于派发结果
public RequestQueue(Cache cache, Network network) {
this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);
}
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
//传递一个与主线程的Looper关联的一个Handler
this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}
其中
mCache : 缓存数据
mNetwork :网络请求
mDispatchers :网络请求调度线程(默认开启4个)
mDelivery :分发响应解析后的数据对象
ExecutorDelivery:结果回调监听分发,请求数据解析后,通过此类回调给调用者,传递一个与主线程的Looper关联的一个Handler,这样做的好处就是调用者可以在回调中更新UI
2. 存储数据集合
PriorityBlockingQueue
:是优先级阻塞队列,在这个数据结构,元素是按照顺序储存的。元素们必须实现 带有compareTo()
方法的 Comparable 接口
。当你在结构中插入数据时,它会与数据元素对比直到找到它的位置;当从队列中获取数据的时候,如果没有数据的时候,会阻塞在take()方法
队列之间的关系
:每当一个请求到来时,先加入到mCurrentRequests
,然后判断当前Request
是否需要缓存,如果不用缓存的Request,则直接加入到mNetworkQueue
队列中等待网络处理器(NetWorkDispatcher)去处理。如果需要缓存的话,根据Request获取相应的cacheKey
,如果cacheKey
不存在的话,说明这个需要缓存的Request是第一次请求。那么将cacheKey
放入到mWaitingRequests
队列里。mWaitingRequests
里存放的是mCacheQueue
里已经有相同url的Request,并将Request放入到mCacheQueue
中以做处理
mCurrentRequests:存储当前请求,主要用于取消请求
mWaitingRequests:主要是为了避免不必要的网络数据获取
3. 启动所有调度器线程
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.
// 网络请求调度器,默认开启DEFAULT_NETWORK_THREAD_POOL_SIZE(4)个线程,相当于线程池
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
开启1个缓存线程,4个网络请求线程(相当于线程池),当将请求add到PriorityBlockingQueue的时候,在运行缓存和网络线程就会接收到请求,从而去处理相对应的请求会阻塞
CacheDispatcher:缓存请求线程
NetworkDispatcher:网络请求调度器
4. 将一个请求加入请求队列中
public <T> Request<T> add(Request<T> request) {
// Tag the request as belonging to this queue and add it to the set of current requests.
request.setRequestQueue(this); //为Request设置请求队列
//将请求add到当前请求队列中
synchronized (mCurrentRequests) {
mCurrentRequests.add(request);
}
// Process requests in the order they are added.
//设置唯一的序列号
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
// If the request is uncacheable, skip the cache queue and go straight to the network.
if (!request.shouldCache()) {
//不缓存,跳过缓存队列直接请求数据
mNetworkQueue.add(request);
return request;
}
// Insert request into stage if there's already a request with the same cache key in flight.
//缓存,首先判断是否有相同请求正在处理
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
//有相同请求正在处理
if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up.
Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new LinkedList<Request<?>>();
}
stagedRequests.add(request);
//处理等待队列空数据,加入到等待队列
mWaitingRequests.put(cacheKey, stagedRequests);
if (VolleyLog.DEBUG) {
VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
}
} else {
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
// 创建新的等待当前请求的空队列添加到当前请求缓存队列中
mWaitingRequests.put(cacheKey, null);
mCacheQueue.add(request);
}
return request;
}
}
5. 其他方法
> public void stop() 停止所有调度器线程
> <T> void finish(Request<T> request) 请求结束调用
> public void cancelAll(final Object tag) 通过Tag取消请求
6. 其他涉及到的类(后续解析)
private final ResponseDelivery mDelivery; 通过子类ExecutorDelivery响应结果分发
private final Network mNetwork; 通过子类BasicNetwork封装网络请求HttpStack,用于执行网络请求
private AtomicInteger mSequenceGenerator = new AtomicInteger(); 生成唯一标识符
private NetworkDispatcher[] mDispatchers; 网络分发数组