您的位置:首页 > 其它

[置顶] Volley源码阅读(0)

2016-11-20 00:03 381 查看


在RequestQueue类中

1、首先看add方法

if (!request.shouldCache()) {
mNetworkQueue.add(request);
return request;
}


在他的add方法中会判断是否需要缓存.shouldCache(),需要则添加到mNetworkQueue网络处理队列,至此返回

否则进入缓存队列处理

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;
}


在加入缓存队列前每个请求得到都会判断该请求是否正在执行(flight)判断条件就是请求的cacheKey是否对应 map集合mWaitingRequests

2、再来看finish方法(因为上面的mWaitingRequest在finish方法中被处理了)

```
<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);
}
}

if (request.shouldCache()) {
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
Queue<Request<?>> waitingRequests = mWaitingRequests.remove(cacheKey);
if (waitingRequests != null) {
if (VolleyLog.DEBUG) {
VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",
waitingRequests.size(), cacheKey);
}
// Process all queued up requests. They won't be considered as in flight, but
// that's not a problem as the cache has been primed by 'request'.
mCacheQueue.addAll(waitingRequests);
}
}
}
```


上面代码中做了这些事:

将请求从mCurrentRequests主队列(存了网络队列和缓存队列)移除了,添加了请求完成监听,如果该请求同时是能被缓存的则把存于mWaitingRequests中的相同请求取出并加入mCacheQueue缓存队列。(个人认为这是为了处理多次相同请求能够依次进行缓存,而HashMap不支持相同键值对存在,所以引入mWaitingRequests)

推测引入mWaitingRequest是为了处理相同请求多次依次处理而作为中间存储空间。

从注释中可以看到

* Called from {@link Request#finish(String)}, indicating that processing of the given request

* has finished.


finish是在Request中的finish被调用的

那么Request中怎么有RequestQueue对象呢?因为Request中有setRequestQueue,在RequestQueue中的add方法一开始就调用了

也就是说每一个被添加到RequestQueue中Request都与RequestQueue绑定了。

3、看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();
}
}
```


先调用了stop方法,将当前的正在运行的dispatchers全部停掉

再创建了缓存分发线程和网络分发线程

CacheDispatcher()中的参数:mCacheQueue–>缓存请求队列 |

mNetworkQueue–>网络请求队列 |-都是实现Queue接口的PriorityBlockingQueue对象,指针

mCache–>缓存操作对象,默认传入的是DiskBasedCache对象(这里用于读取缓存)

mDelivery–>监听接口传递,是实现了ResponseDelivery的子类ExecutorDelivery的对象

|-它的方法postResponse可以用于绑定Response响应结果给监听器

NetworkDispatcher()中的参数:mNetworkQueue–>网络请求队列

mNetwork–>网络请求对象,能够执行网络请求

mCache–>缓存操作对象,默认传入的是DiskBasedCache对象(这里用于写入缓存)

mDelivery–>监听接口传递,是实现了ResponseDelivery的子类ExecutorDelivery的对象

|-它的方法postResponse可以用于绑定Response响应结果给监听器

4、看cancelAll()、stop()方法:

/**
* Cancels all requests in this queue for which the given filter applies.
* @param filter The filtering function to use
*/
public void cancelAll(RequestFilter filter) {
synchronized (mCurrentRequests) {
for (Request<?> request : mCurrentRequests) {
if (filter.apply(request)) {
request.cancel();
}
}
}
}


cancelAll()方法用于将当前的mCurrentRequests集合中全部进行标记取消,理论上只能在线程没开启的时候取消

/**
* Stops the cache and network dispatchers.
*/
public void stop() {
if (mCacheDispatcher != null) {
mCacheDispatcher.quit();
}
for (int i = 0; i < mDispatchers.length; i++) {
if (mDispatchers[i] != null) {
mDispatchers[i].quit();
}
}
}


stop()方法则是调用线程执行quit()方法,理论上可以停止正在执行缓存和网络任务的线程

@see quit()

public void quit() {
mQuit = true;
interrupt();
}


quit()方法标记为true,使线程的while循环退出并调用Thread中的interrupt()方法中断线程。

5、看RequestQueue的构造

```
RequestQueue的核心构造器:
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;
mNetwork = network;
mDispatchers = new NetworkDispatcher[threadPoolSize];
mDelivery = delivery;
}

```


传入缓存执行对象,Volley中的newRequestQueue(),

网络请求mNetworkQueue和缓存队列mCacheQueue都是 PriorityBlockingQueue对象 RequestQueue存储请求用的是set集合(HashSet)

其他备注

1、 LinkedList类实现了Queue接口

2、 锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁,代码块中对该对象有一些处理操作。

3、
//得到Android系统的版本

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)

Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH


4、TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());

5、Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

6、Request中有个isCancel()方法。取消请求,如果请求已经在进行了则不起作用。这个方法是请求还没执行时有作用。也就是说在线程已经开始run了。

7、Request基类中定义了错误监听,因为子类的错误监听都相同,成功的监听都不同,成功的监听结果有String,Json,Image等。

8、Request中有返回监听,有错误返回监听,成功监听有子类设置,有个接口为ResponseDelivery,用于传递监听的,其子类ExecutorDelivery用于绑定Request及其子类的监听与Response的。

9、
BlockingQueue<String> queue = new PriorityBlockingQueue();


这个队列对象相当于指针,对象作为参数传入方法后,改变值会同时在外面被改变;在RequestQueue类中的mNetWorkQueue和mCacheQueue都是这个类型的对象。

//TODO 还有其他的一些关键类再去了解

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: