尊重原创,转载请注明出处,谢谢
很早就想写篇Volley源码解析的文章,但是写文章,特别是写源码解析的文章其实是需要决心的,也是需要时间的,因为你需要把你老早就看过的代码重新理一遍,然后加上注释,然后解析,继上一次写了个Volley的引子后,过去也有一段时间了,终于可以抽出一个周末下午的时间来写一下了,希望对需要的朋友有用的,另外,Volley的源码写的十分出色,可拓展性方面非常强,功能模块十分清晰,所以也是对自我的一次洗礼吧,学习他的设计以及编码也是具有很大的价值的,废话不多说了。
我觉得解析的最好方式就是对照源码给出注释,然后得出结果,所以本文很大一部分解析都写在了代码的注释方面,从代码中来,到代码中去嘛!
先来看一下Volley的使用方式:
private RequestQueue mRequestQueue;
mRequestQueue = Volley.newRequestQueue(this);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,url,null,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
.........
}
},new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
............
}
});
mRequestQueue.add(request);
接下来对Volley的源码进行解析:
1
.从Volley类入手,这里面就是提供了一个创建RequestQueue的方法:newRequestQueue(),有两个重载方法,一个是使用默认的HttpStack,一个是可以自定义HttpStack作为参数传进去。
下面是newRequestQueue()代码及解析:
public static RequestQueue
newRequestQueue(Context context
, HttpStack stack) {
File cacheDir = new File(context.getCacheDir() , DEFAULT_CACHE_DIR) ; // 缓存的文件路径
String userAgent = "volley/0" ;
try {
String packageName = context.getPackageName() ;
PackageInfo info = context.getPackageManager().getPackageInfo(packageName , 0) ;
userAgent = packageName + "/" + info.versionCode ;
} catch (NameNotFoundException e) {
}
if (stack == null) { // 使用 Volley 默认的 HttpStack
if (Build.VERSION.SDK_INT >= 9) { //API 版本在 9 以上则使用 HurlStack, 里面的 performRequest() 是通过 HttpUrlConnection 去实现网络请求的
stack = new HurlStack() ;
} else { //API 版本在 9 以上则使用 HttpClientStack, 里面的 performRequest() 是通过 HttpClient 去实现网络请求的
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)) ;
}
}
//new 一个 BasicNetWork, 这里面主要就是一个 perfromRequest ()方法区发起请求,是通过调 stack 里面的 perfromRequest() 来实现的
Network network = new BasicNetwork(stack) ;
// 创建一个 RequestQueue, 关注传进去的两个参数
RequestQueue queue = new RequestQueue( new DiskBasedCache(cacheDir) , network) ;
queue.start() ;//这个start之后直接开启了整个队请求队列的处理过程,可以看下面对这个方法的解析
return queue ;
File cacheDir = new File(context.getCacheDir() , DEFAULT_CACHE_DIR) ; // 缓存的文件路径
String userAgent = "volley/0" ;
try {
String packageName = context.getPackageName() ;
PackageInfo info = context.getPackageManager().getPackageInfo(packageName , 0) ;
userAgent = packageName + "/" + info.versionCode ;
} catch (NameNotFoundException e) {
}
if (stack == null) { // 使用 Volley 默认的 HttpStack
if (Build.VERSION.SDK_INT >= 9) { //API 版本在 9 以上则使用 HurlStack, 里面的 performRequest() 是通过 HttpUrlConnection 去实现网络请求的
stack = new HurlStack() ;
} else { //API 版本在 9 以上则使用 HttpClientStack, 里面的 performRequest() 是通过 HttpClient 去实现网络请求的
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)) ;
}
}
//new 一个 BasicNetWork, 这里面主要就是一个 perfromRequest ()方法区发起请求,是通过调 stack 里面的 perfromRequest() 来实现的
Network network = new BasicNetwork(stack) ;
// 创建一个 RequestQueue, 关注传进去的两个参数
RequestQueue queue = new RequestQueue( new DiskBasedCache(cacheDir) , network) ;
queue.start() ;//这个start之后直接开启了整个队请求队列的处理过程,可以看下面对这个方法的解析
return queue ;
}
所以可以知道真正发送请求的就是BasicNetWork里的performRequest(),它里面是通过HttpStack的perfromRequest()去发送请求的,而这里面就是利用HttpUrlConnection或HttpClient。所以对Volley最基础的发送请求部分有兴趣的话可以看BasicNetWork.performRequest()。
接下来解析一下RequestQueue:
先来看看RequestQueue类里的几个变量,也是整个框架最重要的几个组成部分:
1.CacheDispatcher :继承自Thread,是一个线程,负责处理走缓存缓存的请求,当调用start()启动之后,会不断的从缓存请求队列中取出请求进行处理,请求处理结束则把结果传递给ResponseDelivery去执行之后的处理,如果结果为缓存过,或者缓存失效或需要重新刷新的情况下,该请求都会重新进入NetWorkDispathcher.
2.NetworkDispatcher:也是一个线程,专门处理走网络的请求,start()后也是不断的从请求队列里取请求,处理请求,获取到结果后把结果传递到ResponseDelivery去执行后续处理,然后在判断是否需要缓存结果。
3.ResponseDelivery:返回结果分发接口
4.Network:就是执行网络请求的,里面的performRequest()就是发送请求并接收结果, 并将结果转换为可被ResponseDelivery处理的NetworkResponse。
5.Cache:缓存请求结果的,默认是DiskBaseCache
上面的这几个类各司其职,比如调度处理请求的、实现发送网络请求的、做缓存的等的,完成各自的工作,还有一个特点就是他们大都都是接口,而不是具体实现类,Volley有大量的面向接口的编程,这极大的加大了框架的灵活性和可拓展性,用户甚至可以自定义实现某个部分的功能。
RequestQueue类内部还有一些变量:
1.mCacheQueue:是一个存放结果已被缓存过的请求的队列,CacheDispather就是每次去这里面取请求进行处理
2.mNetworkQueue:存放进行网络请求的队列,NetworkDispather就是每次去这里面取请求进行处理的
上面两个队列的类型都是BlockingQueue:是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用,十分适合这种场景。
3.NetworkDispatcher[] mDispatchers:就是一个放Networkdispather的数组,默认定义容量是4
上面就是RequestQueue类里面的一些重要变量了,接下来看看它里面的方法,主要就是两个,一个start(),可以看到上面Volley.newRequestQueue()里面最后就调了start();还有一个是add(),就是把请求加入Queue中。
1.start():
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() ; // 开启 CacheDispather 线程,开始处理 mCacheQueue 中的请求
// Create network dispatchers (and corresponding threads) up to the pool size.
// 循环开启数组里的 NetworkDispatcher 线程,开始处理 mNetworkQueue 中的请求
for ( int i = 0 ; i < mDispatchers.length ; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue , mNetwork ,
mCache , mDelivery) ;
mDispatchers[i] = networkDispatcher ;
networkDispatcher.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() ; // 开启 CacheDispather 线程,开始处理 mCacheQueue 中的请求
// Create network dispatchers (and corresponding threads) up to the pool size.
// 循环开启数组里的 NetworkDispatcher 线程,开始处理 mNetworkQueue 中的请求
for ( int i = 0 ; i < mDispatchers.length ; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue , mNetwork ,
mCache , mDelivery) ;
mDispatchers[i] = networkDispatcher ;
networkDispatcher.start() ;
}
}
下面具体看一下CacheDispather start之后,里面的run是如果处理mCacheQueue里的请求的,也就是CacheDispather里面的run()方法:
@Override
public void run() {
if (DEBUG) VolleyLog.v( "start new dispatcher") ;
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) ;
// Make a blocking call to initialize the cache.
mCache.initialize() ;
while ( true) { // 无限循环取请求,处理请求
try {
// 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") ;
// If the request has been canceled, don't bother dispatching it.
if (request.isCanceled()) { // 如果请求已被取消
request.finish( "cache-discard-canceled") ;
continue;
}
// Attempt to retrieve this item from cache.
// 到 Cache 根据 key 取出相应的结果 entry
Cache.Entry entry = mCache.get(request.getCacheKey()) ;
// 如果结果为 null, 则打上缓存消失的标志,然后把请求加入 NetworkQueue ,重新进行网络请求
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.
// 如果缓存的请求结果已过期,则同样打个标志,然后放进 NetwoekQueue 重新请求
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") ;
// 把结果转化为 NetworkResponse 类型
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data , entry.responseHeaders)) ;
request.addMarker( "cache-hit-parsed") ;
// 如果结果是不需要刷新的,则直接发送给 ResponseDelivery 进行分发
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request , response) ;
}
// 如果结果是需要刷新的,则也是先把结果发送给 ResponseDelivery 进行分发,然后再放进 NetworkQueue 中进行网络请求
// 这样可以先展示缓存的结果,然后又去请求网络回来就可以刷新结果了
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.
mDelivery.postResponse(request , response , new Runnable() {
@Override
public void run() {
try {
mNetworkQueue.put( request) ;
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
}) ;
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
}
}
public void run() {
if (DEBUG) VolleyLog.v( "start new dispatcher") ;
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) ;
// Make a blocking call to initialize the cache.
mCache.initialize() ;
while ( true) { // 无限循环取请求,处理请求
try {
// 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") ;
// If the request has been canceled, don't bother dispatching it.
if (request.isCanceled()) { // 如果请求已被取消
request.finish( "cache-discard-canceled") ;
continue;
}
// Attempt to retrieve this item from cache.
// 到 Cache 根据 key 取出相应的结果 entry
Cache.Entry entry = mCache.get(request.getCacheKey()) ;
// 如果结果为 null, 则打上缓存消失的标志,然后把请求加入 NetworkQueue ,重新进行网络请求
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.
// 如果缓存的请求结果已过期,则同样打个标志,然后放进 NetwoekQueue 重新请求
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") ;
// 把结果转化为 NetworkResponse 类型
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data , entry.responseHeaders)) ;
request.addMarker( "cache-hit-parsed") ;
// 如果结果是不需要刷新的,则直接发送给 ResponseDelivery 进行分发
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request , response) ;
}
// 如果结果是需要刷新的,则也是先把结果发送给 ResponseDelivery 进行分发,然后再放进 NetworkQueue 中进行网络请求
// 这样可以先展示缓存的结果,然后又去请求网络回来就可以刷新结果了
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.
mDelivery.postResponse(request , response , new Runnable() {
@Override
public void run() {
try {
mNetworkQueue.put( request) ;
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
}) ;
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
}
}
上面的代码已经十分清晰的的解析了CacheDispatcher线程取请求处理请求的过程,可以看到取结果是到Cache里面去取的,那下面就解析一下这个Cache:
Cache只是一个接口,里面定义了对结果的存、取、删除等方法,而DiskBasedCache才是真正的实现类,先来看一下Cache里面缓存结果的一个实体Entry:
public static class Entry {
/** The data returned from cache. */
public byte[] data ; // 结果数据
/** ETag for cache coherency. */
public String etag ; // 标签,如消失、过期等
/** Date of this response as reported by the server. */
public long serverDate ; // 网络请求回来的时间
/** The last modified date for the requested object. */
public long lastModified ; // 上一次刷新的时间
/** TTL for this record. */
public long ttl ;
/** Soft TTL for this record. */
public long softTtl ;
/** Immutable response headers as received from server; must be non-null. */
public Map<String , String> responseHeaders = Collections.emptyMap() ;
/** True if the entry is expired. */
// 是否过期
public boolean isExpired() {
return this. ttl < System. currentTimeMillis() ;
}
/** True if a refresh is needed from the original data source. */
// 是否需要刷新
public boolean refreshNeeded() {
return this. softTtl < System. currentTimeMillis() ;
}
}
/** The data returned from cache. */
public byte[] data ; // 结果数据
/** ETag for cache coherency. */
public String etag ; // 标签,如消失、过期等
/** Date of this response as reported by the server. */
public long serverDate ; // 网络请求回来的时间
/** The last modified date for the requested object. */
public long lastModified ; // 上一次刷新的时间
/** TTL for this record. */
public long ttl ;
/** Soft TTL for this record. */
public long softTtl ;
/** Immutable response headers as received from server; must be non-null. */
public Map<String , String> responseHeaders = Collections.emptyMap() ;
/** True if the entry is expired. */
// 是否过期
public boolean isExpired() {
return this. ttl < System. currentTimeMillis() ;
}
/** True if a refresh is needed from the original data source. */
// 是否需要刷新
public boolean refreshNeeded() {
return this. softTtl < System. currentTimeMillis() ;
}
}
下面接着看一下NetworkDispatcher里面是如何处理mNetworkQueue里的请求的,同样看他的run()方法里:
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) ;
while ( true) { // 开启无限循环取请求,处理请求
long startTimeMs = SystemClock.elapsedRealtime() ;
Request<?> request ;
try {
// Take a request from the queue.
request = mQueue.take() ; // 取请求
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
try {
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;
}
addTrafficStatsTag(request) ;
// Perform the network request.
// 调用 NetWork 的 performRequest ()来发送网络请求,并获取到结果 NetworkResponse
NetworkResponse networkResponse = mNetwork.performRequest(request) ;
request.addMarker( "network-http-complete") ;
// If the server returned 304 AND we delivered a response already,
// we're done -- don't deliver a second identical response.
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish( "not-modified") ;
continue;
}
// Parse the response here on the worker thread.
// 转化 response 为我们想要的结果实体类型
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.
// 判断结果是否需要被缓存,如果需要,则缓存进 Cache
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey() , response.cacheEntry) ;
request.addMarker( "network-cache-written") ;
}
// Post the response back.
request.markDelivered() ;
// 发送结果给 ResponseDelivery 分发出去
mDelivery.postResponse(request , response) ;
} catch (VolleyError volleyError) {
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs) ;
parseAndDeliverNetworkError(request , volleyError) ;
} catch (Exception e) {
VolleyLog.e(e , "Unhandled exception %s" , e.toString()) ;
VolleyError volleyError = new VolleyError(e) ;
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs) ;
mDelivery.postError(request , volleyError) ;
}
}
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) ;
while ( true) { // 开启无限循环取请求,处理请求
long startTimeMs = SystemClock.elapsedRealtime() ;
Request<?> request ;
try {
// Take a request from the queue.
request = mQueue.take() ; // 取请求
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
try {
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;
}
addTrafficStatsTag(request) ;
// Perform the network request.
// 调用 NetWork 的 performRequest ()来发送网络请求,并获取到结果 NetworkResponse
NetworkResponse networkResponse = mNetwork.performRequest(request) ;
request.addMarker( "network-http-complete") ;
// If the server returned 304 AND we delivered a response already,
// we're done -- don't deliver a second identical response.
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish( "not-modified") ;
continue;
}
// Parse the response here on the worker thread.
// 转化 response 为我们想要的结果实体类型
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.
// 判断结果是否需要被缓存,如果需要,则缓存进 Cache
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey() , response.cacheEntry) ;
request.addMarker( "network-cache-written") ;
}
// Post the response back.
request.markDelivered() ;
// 发送结果给 ResponseDelivery 分发出去
mDelivery.postResponse(request , response) ;
} catch (VolleyError volleyError) {
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs) ;
parseAndDeliverNetworkError(request , volleyError) ;
} catch (Exception e) {
VolleyLog.e(e , "Unhandled exception %s" , e.toString()) ;
VolleyError volleyError = new VolleyError(e) ;
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs) ;
mDelivery.postError(request , volleyError) ;
}
}
}
上面我们已经知道了Volley是如何取请求,处理请求的,接下来看一下ResponseDelivery这个类,上面我们发现得到结果后都会调ResponseDelivery.postResponse()来分发结果:
同样的ResponseDelivery是一个接口,里面主要有一下三个方法:
1.postResponse(Request<?> request, Response<?> response) :分发Response
2.postResponse(Request<?> request, Response<?> response, Runnable runnable):同上
3.postError(Request<?> request, VolleyError error):分发error
而它的具体实现类是:ExecutorDelivery
所以来看看ExecutorDelivery中的PostResponse()方法:
public void
postResponse(Request<?> request
, Response<?> response
, Runnable runnable) {
request.markDelivered() ;
request.addMarker( "post-response") ;
mResponsePoster.execute( new ResponseDeliveryRunnable(request , response , runnable)) ;
}
request.markDelivered() ;
request.addMarker( "post-response") ;
mResponsePoster.execute( new ResponseDeliveryRunnable(request , response , runnable)) ;
}
可以看到最后是执行了一个Runable:ResponseDeliveryRunable,所以我们看看这个Runable里面的run():
@Override
public void run() {
// If this request has canceled, finish it and don't deliver.
if (mRequest.isCanceled()) {
mRequest.finish( "canceled-at-delivery") ;
return;
}
// Deliver a normal response or error, depending.
// 调用 Request 里面的 deliverResponse( )方法
if (mResponse.isSuccess()) {
mRequest.deliverResponse(mResponse.result) ;
} else {
mRequest.deliverError(mResponse.error) ;
}
// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
if (mResponse.intermediate) {
mRequest.addMarker( "intermediate-response") ;
} else {
mRequest.finish( "done") ;
}
// If we have been provided a post-delivery runnable, run it.
if (mRunnable != null) {
mRunnable.run() ;
}
public void run() {
// If this request has canceled, finish it and don't deliver.
if (mRequest.isCanceled()) {
mRequest.finish( "canceled-at-delivery") ;
return;
}
// Deliver a normal response or error, depending.
// 调用 Request 里面的 deliverResponse( )方法
if (mResponse.isSuccess()) {
mRequest.deliverResponse(mResponse.result) ;
} else {
mRequest.deliverError(mResponse.error) ;
}
// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
if (mResponse.intermediate) {
mRequest.addMarker( "intermediate-response") ;
} else {
mRequest.finish( "done") ;
}
// If we have been provided a post-delivery runnable, run it.
if (mRunnable != null) {
mRunnable.run() ;
}
}
可以看到是调用了Request里面的deliverResponse(),而Request是一个抽象类,具体的分发工作要由继承了Request的具体类来实现这个deliverResponse(),比如Volley封装的StringRequest等等,那么我们可以继承Request来实现这个deliverResponse()实现对结果的分发。
首先是定义一个listener接口:
public interface IResponseListener<
T
extends IResponse> {
void onSuccess(BaseRequest< T> request , T response) ;
void onFail(BaseRequest< T> request , T response , ErrorCodeExtend error) ;
void onSuccess(BaseRequest< T> request , T response) ;
void onFail(BaseRequest< T> request , T response , ErrorCodeExtend error) ;
}
然后实现一个类继承自Request,实现deliverResponse():
@Override
protected void deliverResponse( T response) {
if ( responseListener != null) {
responseListener.onSuccess( this, response) ;
}
protected void deliverResponse( T response) {
if ( responseListener != null) {
responseListener.onSuccess( this, response) ;
}
}
这样就通过回调实现了对返回结果的分发,只要我们创建一个Request的时候,这个responseListener就是参数之一,这个时候想起Volley的用法:
Request request=new Request(new IResponseListener(){
onSuccess(){
..........
}
})
也就知道了。
上面基本以及解析了Volley是如何从队列中取请求,处理请求,缓存,以及分发返回结果的过程,那么还有一个过程是把请求添加进队列里,这个过程我们使用Volley的时候是通过调用RequestQueue.add()方法来实现的,那么最后就来解析一下这个方法:
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) ;
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.
// 如果此请求是不需要缓存的,则直接加进 mNetworkQueue ,结束
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
mCacheQueue.add(request) ;
}
return request ;
}
// Tag the request as belonging to this queue and add it to the set of current requests.
request.setRequestQueue( this) ;
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.
// 如果此请求是不需要缓存的,则直接加进 mNetworkQueue ,结束
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
mCacheQueue.add(request) ;
}
return request ;
}
}
这就是把Request加进队列的过程。
至此,对Volley源码的解析也差不多结束了。
总结:
通过对Volley源码的解析,可以看出来这是一个写的十分优秀的开源项目,各模块分工十分明确,基本上都是面对接口编程,框架的可拓展性非常强,你可以自己实现某一模块的功能,然后像插件一样插进去,当然你也可以使用Volley帮你实现的默认的模块,拔插十分方便,这就是一个优秀的框架该有的样子吧,对用户十分友好,我想Volley应该是很多想自己写框架的朋友一个良好的借鉴。