Volley 核心源码解析(三)

[size=large][color=orange]Volley 的任务调度模型[/color][/size]

接着上一节的 RequestQueue,在Volley 初始化 RequestQueue的时候 会执行 RequestQueue 的 start()方法,在start方法中 初始化了,缓存调度器和网络调度器。

[b] 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();
}
}
[/b]

[b]看看NetworkDispatcher 和 CacheDispatcher 是什么东东?[/b]

[color=red]NetworkDispatcher extends Thread

CacheDispatcher extends Thread[/color]

结果两个都是线程类。

再看看循环体中 往一个叫做mDispatchers[i] 的数组中赋值了若干 NetworkDispatcher,且每个NetworkDispatcher都在创建的时候 就启动了。

[color=brown]找到 mDispatchers的定义:
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;

mDispatchers = new NetworkDispatcher[threadPoolSize];

原来是个默认4个元素的 线程组。

看到这里我似乎想到了线程池的基本概念,没错 这就是个线程池。[/color]


[color=orange][b]看看具体的 NetworkDispatcher 是什么样的?[/b][/color]

做过JAVA 开发的都知道 继承 thread 类一定要重写 run()方法

在NetworkDispatcher中run 方法如下:

方法太长 一段一段的来看哈

因为是要做线程池嘛,所以线程要一直工作,所以一进run方法 就是 while(true){}
了,

[color=red][b] Request<?> request = mQueue.take();[/b][/color]

mQueue:mNetworkQueue

在 PriorityBlockingQueue 队列中 take 方法如下:
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
E result;
try {
while ( (result = dequeue()) == null)
notEmpty.await();
} finally {
lock.unlock();
}
return result;
}
[size=large][color=brown]
意思就是加锁 -->取出一个请求->释放锁->原队列中请求减少一个

这样就保证了 使用 volley 发送请求的时候 能按照发送请求的顺序去执行。[/color][/size]

接下来 从队列中取出请求之后,给请求设置备注,判断请求时否被取消,如果被取消就finish。

[align=left] request.addMarker("network-queue-take");

// If the request was cancelled already, do not perform the
// network request.
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
continue;
}[/align]


紧接着,执行该请求:
// Perform the network request.
[color=red]NetworkResponse networkResponse = mNetwork.performRequest(request);[/color]

后面就是对 networkResponse 的一些状态判断和解析。

[color=red]Response<?> response = request.parseNetworkResponse(networkResponse);[/color]

在volley 中 解析NetworkResponse 的具体方法 交给 Request 的 子类去实现。如,ImageRequest,JsonRequest,StringRequest等

同时,缓存 这个已经执行的请求:
if (request.shouldCache() && response.cacheEntry != null) {
[color=red]mCache.put(request.getCacheKey(), response.cacheEntry);[/color]
request.addMarker("network-cache-written");
}


[size=large][color=orange]看到这里,我们可以得出一个结论,Volley 初始化 RequestQueue 的时候 创建了一个
默认4个大小的线程池,每个线程同步 的从PriorityBlockingQueue 类型的请求队列中拿出一个请求并执行。[/color][/size]

[b][color=red]
接下来看看 CacheDispatcher 缓存任务调度:[/color][/b]

/** The queue of requests coming in for triage. */
private final BlockingQueue<Request<?>> mCacheQueue;

/** The queue of requests going out to the network. */
private final BlockingQueue<Request<?>> mNetworkQueue;

与 NetworkDispatcher 不同的是 CacheDispatcher 不仅有缓存队列 还有请求队列,

同样是while (true) { request = mCacheQueue.take();; ...}

不停的从 mCacheQueue 拿出缓存过的请求:
// 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;
}
这里看到 被缓存的请求时根据请求的cacheKey 从cache中取出,如果取出的缓存为空,直接把请求 放到 mNetworkQueue ,也就是说把请求交给 了 NetworkDispatcher去执行。

如果请求的缓存对象过期,同上:
// If it is completely expired, just send it to the network.
if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
[color=red] mNetworkQueue.put(request);[/color]
continue;
}
[size=large][color=red]这里我们看到一个关键性的代码:
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));[/color][/size]

这是什么意思呢?

[size=large][color=orange] Volley不仅缓存了请求本身,而且缓存了请求的响应结果,此时做的就是从缓存中取出响应的结果,这样就不用再发请求去服务器上了。[/color][/size]

接下来,

if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
[color=red] mDelivery.postResponse(request, response);[/color]
} else {
// Soft-expired cache hit. We can deliver the cached response,
// but we need to also send the request to the network for
// refreshing.
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);

// Mark the response as intermediate.
response.intermediate = true;

// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
final Request<?> finalRequest = request;
mDelivery.postResponse(request, response, new Runnable() {
@Override
public void run() {
try {
[color=red]mNetworkQueue.put(finalRequest);[/color]
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
});
}

如果缓存数据不需要刷新,只需要用回掉接口返回值,反之,把请求放入mNetworkQueue,等待 NetworkDispatcher 执行。


[size=large][color=orange]至此,Volley 的 线程模型分析告一段落,我们看到了线程组 NetworkDispatcher[] 和 单线程 CacheDispatcher 通过 两个 BlockingQueue 巧妙地实现了网络请求任务的交替轮换。[/color][/size]


下一节 Volley的缓存 [url]http://f303153041.iteye.com/blog/2281360[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值