Part 1.从RequestQueue说起
Volley框架的使用
Android Volley完全解析(一),初识Volley的基本用法
http://blog.csdn.net/guolin_blog/article/details/17482095
(1)还记得搭建请求的第一步是什么吗?是新建一个请求队列,比如说这样:
RequestQueue queue = Volley.newRequestQueue(context)
虽然表面上只是一句代码的事情,但是背后做了很多准备工作,我们追踪源码,找到Volley#newRequestQueue()方法:
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes)
到目前为止,Volley.newRequestQueue()方法完成了,即我们的网络请求第一步,建立请求队列完成。
先小结一下 : 建立请求队列所做的工作是,创建文件缓存(默认),实例化BasicNetwork,实例化Delivery用于发送线程请求,创建一条缓存线程和四条网络请求线程(默认)并运行。
art 2.网络请求的实现原理
在创建完请求队列后,接着就是建立一个请求,请求的方式可以是StringRequest、JsonArrayRequest或者ImageRequest等。它继承自Request,而Request则是所有请求的父类这里 小结一下: Request类做的工作主要是初始化一些参数,比如说请求类型、请求的url、错误的回调方法;而它的任一子类重写deliverResponse方法来实现成功的回调,重写parseNetworkResponse()方法来处理响应数据;至此,一个完整的Request请求搭建完毕。
Part 3.添加请求
前面已经完成了请求队列的创建,Request请求的创建,那么接下来就是把请求添加进队列了。我们看RequestQueue#add()源码:
得出如下结论:在这个add方法中,主要判断一个Request请求是否可以缓存(默认是可以缓存的),如果不可以则直接添加到网络请求队列开始网络通信;如果可以,则进一步判断当前是否有相同的请求正在进行,如果有相同的请求,则让这个请求排队等待,如果没有相同的请求,则直接放进缓存队列中。如果对此还有什么疑问,可以看下面的流程图(图片来自网络):
Part 4.缓存线程
在part1的最后实例化了缓存线程并开始运行,一直处于等待状态,而上面把请求添加进了缓存线程,此时缓存线程就开始真正的工作了。我们来看缓存线程的源码,主要看它的run()方法,CacheDispatcher#run():
小结:CacheDispatcher线程主要对请求进行判断,是否已经有缓存,是否已经过期,根据需要放进网络请求队列。同时对相应结果进行包装、处理,然后交由ExecutorDelivery处理 。
Part 5.网络请求线程
上面提到,请求不能缓存、缓存结果不存在、缓存过期的时候会把请求添加进请求队列,此时一直等待的网络请求线程由于获取到请求,终于要开始工作了,我们来看NetworkDispatcher#run()方法:
Part 6.ExecutorDelivery 通知主线程
public ExecutorDelivery(final Handler handler) {
// Make an Executor that just wraps the handler.
//实例化Executor,并且重写execute方法
mResponsePoster = new Executor() {
@Override
public void execute(Runnable command) {
//这里获取的handler是主线程的handler,可看part 1 (2)
handler.post(command);
}
};
}
execute()方法接收一个Runnable对象,那么我们回到上面的
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
可以看出这里实例化了一个ResponseDeliveryRunnable对象作为Runnable对象。而这里的ResponseDeliveryRunnable则是当前类Executor的一个内部类,实现了Runnable接口,我们来看看:
/**
* A Runnable used for delivering network responses to a listener on the
* main thread.
*/
@SuppressWarnings("rawtypes")
private class ResponseDeliveryRunnable implements Runnable {
private final Request mRequest;
private final Response mResponse;
private final Runnable mRunnable;
//构造方法
...
@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.
if (mResponse.isSuccess()) {
mRequest.deliverResponse(mResponse.result); // 1
} else {
mRequest.deliverError(mResponse.error);
}
...
}
}
}
在上面,①号代码回调到了Request的deliverResponse方法,即此时通知了主线程,请求已经完成,此时在Request子类重写的deliverResponse方法则会调用onResponse()方法,那么我们的Activity就能方便调用解析好的请求结果了。
到目前为止,关于Volley的源码解析完毕。
与HttpClient的对比
1. HttpClient只是一个单纯的网络请求类库,比HttpUrlConnection(ANDROIDSDK当中,Android2.3之前有问题)强大很多,可以对HTTP协议头和BODY部分进行方便的修改。 Android的SDK本身也纳入了HttpClient,但处理文件上传和下传不行,还需要使用APACHE的HttpClient。HttpClient没有处理多线程问题,使用者需要配合AsyncTask来使用,AsyncTask处理了线程问题。
Volley的HttpStack提供了两种实现,分别使用了HttpUrlConnection和HttpClient,老版本使用了HttpClient,新版本加入了HttpUrlConnection的HttpStack实现,并且缺省是使用HttpUrlConnection,用户可通过设置来使用HttpClient的HttpStack实现。
2. HttpClient没有提供缓存功能,而Volley实现图片缓存和HTTP的CACHE机制。
3. HttpClient是不能在UI线程里面调用的,否则会出现ANR问题,而Volley是可以在UI线程里面调用的,因为它自己已经使用了线程池来做网络请求,使用者需要提供回调函数来出来网络响应。
4. 使用VOLLEY还需要考虑线程资源关闭的问题,而HttpClient不需要管理这些。
5. 因为线程池的问题,HttpClient是同步调用,而VOLLEY是异步调用。
如果我们实现一个Network访问的Façade,提供HttpClient和Volley两种实现,那么在接口定义上面就需要考虑这两个框架调用上的不同,同步和异步问题。还要考虑资源释放的问题。