}//(2.1)
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
this(cache, network, threadPoolSize,//ExecutorDelivery类是Volley框架中的结果分发类
new ExecutorDelivery(new Handler(Looper.getMainLooper())));//传入Handler是为了能够让需要的方法跑在主线程
}//(2.2)
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache;//缓存处理类的实例
mNetwork = network;//网络处理类的实例
mDispatchers = new NetworkDispatcher[threadPoolSize];//网络调度器的实例
mDelivery = delivery;//结果分发类的实例
}//(2.3)
到这儿终于创建好RequestQueue了,紧接着是start,开启1条缓存调度和4条网络调度。
public void start() {
stop(); // 终止正在运行的线程,缓存调度mCacheDispatcher.quit(),网络调度mDispatchers循环quit(),暂停线程
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();//开启缓存调度
for (int i = 0; i < mDispatchers.length; i++) {//开启网络调度,一般4条
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}(2.4)
(3)网络调度类NetworkDispatcher,这个类继承Thread类,本身是一个线程,只有一个构造方法,重写了run方法。
NetworkDispatcher只负责调度并不负责具体的网络请求,它相当于一个中转站,只是将request从RequestQueue手中取来,然后原封不动的交给mNetwork
public NetworkDispatcher(BlockingQueue<Request<?>> queue,Network network, Cache cache, ResponseDelivery delivery) {
mQueue = queue;//优先级队列
mNetwork = network;//网络处理器
mCache = cache;//缓存处理器
mDelivery = delivery;//结果分发类
}(3.1)
在请求队列start()的时候,就创建并开启了4条网络线程调度,所以看下NetworkDispatcher的run方法:
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//设置最高线程优先级
while (true) {//while死循环,不断的试图从mQueue队列中取出request
long startTimeMs = SystemClock.elapsedRealtime();
Request<?> request;
try {
request = mQueue.take();
} catch (InterruptedException e) {
if (mQuit) {//interrupt()会尝试中断本线程,我们可能会被打断,因为这是该放弃的时候了
return;
}
continue;
}
try {
request.addMarker("network-queue-take");// 调试标记:以成功取出队列中的request
if (request.isCanceled()) {//如果请求被取消,则不再继续请求
request.finish("network-discard-cancelled");
continue;
}
addTrafficStatsTag(request);// 流量统计标记,如果api大于14,配合DDMS工具统计流量使用情况
// 开始真正的网络请求,从这儿看出NetworkDispatcher为什么是网络调度线程,因为它只负责将request传给mNetwork网络
处理类,本身并不执行网络请求,这个方法返回的是NetworkResponse(一个实体类,封装返回数据,封装的参数分别是int状态码,byta[]返回数据,Map<String,String>响应头,boolean无修改标记)
NetworkResponse networkResponse = mNetwork.performRequest(request);
request.addMarker("network-http-complete");//调试标记:网络请求完成(因线程异步,该标记只做调试之用)
// 如果服务器返回无修改,并requset以完成分发,说明进行了重复的请求,移除该request
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
continue;
}
// 交由Request进行解析Response
//parseNetworkResponse是Request抽象类的一个抽象方法,实现方法由Request的子类去实现
Response<?> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");// 调试标记:网络请求解析完成
// 如果需要缓存,将返回的数据加入到缓存处理类中
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
// 最后由结果分发类调用postResponse发起回调
request.markDelivered();
mDelivery.postResponse(request, response);
} catch (VolleyError volleyError) {
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
parseAndDeliverNetworkError(request, volleyError); //此方法通过request.parseNetworkError(volleyError)解析这个错误,然后发起错误回调,值得一提的是parseNetworkError在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);
}
}
}(3.2)
public void quit() {//在RequestQueue调用stop时被调用了
mQuit = true;//标记取消网络请求,并中断该线程,mQuit 为true,则该线程跳出while循环
interrupt();
}(3.3)
`(4)NetworkDispatcher只负责中转,从RequestQueue取出request交给接口NetWork,BasicNetwork是接口的实现类:`
public interface Network {//里面只有一个方法,用于执行请求
public NetworkResponse performRequest(Request<?> request) throws VolleyError;
}(4.1)
在newRequestQueue时,实现了网络接口,Network network = new BasicNetwork(stack);,随后这个network便传给了请求队列,然后又传给网络调度器,最后调用mNetwork.performRequest(request)执行网络请求。
public BasicNetwork(HttpStack httpStack) {//在newRequestQueue时新建的构造方法
this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));//创建了缓存池,大小4096,即4KB
}(4.2)
public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) {
mHttpStack = httpStack;
mPool = pool;
}(4.3)
(4.4)performRequest返回的是一个封装返回数据的实体类对象。这个方法只是对网络请求返回数据的封装处理
@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();//得到开机时间的毫秒值
while (true) {//while死循环
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = Collections.emptyMap();
try {
Map<String, String> headers = new HashMap<String, String>();
addCacheHeaders(headers, request.getCacheEntry());//添加缓存请求头
httpResponse = mHttpStack.performRequest(request, headers);//看出真正执行网络请求的是mHttpStack
StatusLine statusLine = httpResponse.getStatusLine();//得到状态行
int statusCode = statusLine.getStatusCode();//得到状态码
responseHeaders = convertHeaders(httpResponse.getAllHeaders());//得到响应头
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//返回304无修改,则返回
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, statusLine.getReasonPhrase(), entry.data,
entry.responseHeaders, true,
SystemClock.elapsedRealtime() - requestStart);
}
if (httpResponse.getEntity() != null) {//返回204无修改,没有读出内容就给一个0长度字节的数组
responseContents = entityToBytes(httpResponse.getEntity());
} else {
responseContents = new byte[0];
}
// if the request is slow, log it.
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
logSlowRequests(requestLifetime, request, responseContents, statusLine);//调试信息
if (statusCode < 200 || statusCode > 299) {
throw new IOException();//状态码不正确抛出异常
}//经过以上种种判断,封装成NetWorkResponse给予返回
return new NetworkResponse(statusCode, statusLine.getReasonPhrase(), responseContents, responseHeaders, false,SystemClock.elapsedRealtime() - requestStart);//返回封装的数据,状态码,返回数据,响应头,无修改标记
} catch (SocketTimeoutException e) {//尝试重新请求,重试策略类RetryPolicy,在Request的构造方法中创建,先获取对象
attemptRetryOnException("socket", request, new TimeoutError());//retryPolicy= request.getRetryPolicy();
} catch (ConnectTimeoutException e) {//然后调用retryPolicy.retry(exception);
attemptRetryOnException("connection", request, new TimeoutError());
} catch (MalformedURLException e) {
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {
throw new NoConnectionError(e);
}
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
if (responseContents != null) {
networkResponse = new NetworkResponse(statusCode, httpResponse.getStatusLine().getReasonPhrase(), responseContents,
responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
statusCode == HttpStatus.SC_FORBIDDEN) {
attemptRetryOnException("auth",
request, new AuthFailureError(networkResponse));
} else {
// TODO: Only throw ServerError for 5xx status codes.
throw new ServerError(networkResponse);
}
} else {
throw new NetworkError(networkResponse);
}
}
}
}
(5)HttpStack的源码
//Request封装了超时时间,请求方式、参数、url等网络请求所必须的参数,通过变换不同的属性参数(最基本的如请求方式GET和Post),可以获取不同的网络请求。而真正的网络请求是HttpStack
public interface HttpStack {Volley中真正去执行联网的类,返回的信息封装成HttpResponse
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)throws IOException, AuthFailureError;//真正去执行联网的方法,与NetWork接口的一个方法同名
}
对于HttpClientStack和HurlStack,二者的工作思路是:
首先从volley的request内获取各个属性,如超时间、请求方式、url、参数;
然后创建网络请求,HttpClientStack创建HttpClient,HurlStack创建HttpURLConnection;
对网络请求设置各个属性参数。
最后定义执行网络请求的方法,并获取响应,将响应返回去。
以上思路在源码细节中是从HurlStack的performRequest开始
public HurlStack() {this(null);}
public HurlStack(UrlRewriter urlRewriter) {this(urlRewriter, null);}
public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {
mUrlRewriter = urlRewriter;//是HurlStack的一个内部接口,用于URL的重置,一般给null
mSslSocketFactory = sslSocketFactory;//https协议用到的类,一般也是null
}
![](https://img-blog.csdnimg.cn/20190827220442739.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppdWppYW9wYW5kdW9sYQ==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20190827220735869.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppdWppYW9wYW5kdW9sYQ==,size_16,color_FFFFFF,t_70)
其中传入的参数request,里面设置了很多http的属性,如超时,是否缓存,还有一个参数设置头信息
再看看其中几个重要方法:openConnection,setConnectionParametersForRequest ,entityFromConnection
private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
HttpURLConnection connection = createConnection(url);//很简单,只是创建了HttpURLConnection,
通过 url.openConnection()
int timeoutMs = request.getTimeoutMs();
connection.setConnectTimeout(timeoutMs);//设置HttpURLConnection的一些参数,连接超时
connection.setReadTimeout(timeoutMs);//读超时
connection.setUseCaches(false);//关闭缓存
connection.setDoInput(true);//开启输入
if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {//支持https
((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
}
return connection;//返回HttpURLConnection对象
}
setConnectionParametersForRequest :设置请求方式,包含get,delete,post,put等
private static HttpEntity entityFromConnection(HttpURLConnection connection) {
BasicHttpEntity entity = new BasicHttpEntity();//设置实体
InputStream inputStream;
try {
inputStream = connection.getInputStream();
} catch (IOException ioe) {
inputStream = connection.getErrorStream();
}
entity.setContent(inputStream);
entity.setContentLength(connection.getContentLength());
entity.setContentEncoding(connection.getContentEncoding());
entity.setContentType(connection.getContentType());
return entity;//将connection得到的信息封装成实体(BasicHttpEntity)返回
}
到这儿volley网络请求这一条线已经全部完成。
(6)接下来看缓存调度器CacheDispatcher,也是一个线程,继承Thread,也是在请求队列的start方法中调用的start方法
public CacheDispatcher(
BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,
Cache cache, ResponseDelivery delivery) {
mCacheQueue = cacheQueue;//缓存队列
mNetworkQueue = networkQueue;//网络队列
mCache = cache;//缓存处理类
mDelivery = delivery;//结果分发类
}
@Override
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher");
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mCache.initialize();//将缓存数据读入内存,初始化了缓存数据
while (true) {
try {
final Request<?> request = mCacheQueue.take();//从缓存队列中取出request
request.addMarker("cache-queue-take");//调试信息
if (request.isCanceled()) {//如果请求已取消,则中断任务
request.finish("cache-discard-canceled");
continue;
}
Cache.Entry entry = mCache.get(request.getCacheKey());//试图从缓存中取得该项目
if (entry == null) {//是空的就加入网络队列
request.addMarker("cache-miss");
mNetworkQueue.put(request);
continue;
}
if (entry.isExpired()) {//如果缓存过期,加入网络队列
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}