有了前面的velley的使用和学习笔记,今天来学习volley源码
我们就是从使用volley的三部曲来分析;
第一步;获取RequestQueue;
`Volley.newRequestQueue(this);`
我们在说过 获取RequestQueue的方法有两种:我们分别看看;
Volley.class类中:
第一个获取方法(我们学习使用的时候都是这种方法):
`public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, (HttpStack)null);
}`
第二种方法:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), "volley");
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException var6) {
;
}
if (stack == null) {
if (VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork((HttpStack)stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
我们可以看到实际上,我们第一个方法,在Volley总调用的是第二个方法来最后获取RequestQueu的,我们重点来看下面的代码:
if (stack == null) {
if (VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork((HttpStack)stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
我们使用第一种来获取传递的参数只用context,实际上,内部是一个context和(HttpStack)类型的null参数,
当HttpStack是null是后,根据版本创建了HurlStack和HttpClientStack;
** 当版本大于等于9,HurlStack,低于是HttpClientStack**
我们后面分别看看,HttpStack和HurlStack及其HttpClientStack;继续看Volley源码,出现一个NetWork类,下面new了一个RequestQueue对象并start()了,返回了RequestQueue对象.,我们顺便看看NetWork源码.
源码:
public interface HttpStack {
HttpResponse performRequest(Request> var1, Map var2) throws IOException, AuthFailureError;
}
我们看到HttpStack是一个接口,里面只有一个performRequest(参数1,参数2);
我们记住这个方法就行,后面根据接口实现来看.
部分源码:
public class HurlStack implements HttpStack {
private static final String HEADER_CONTENT_TYPE = "Content-Type";
private final HurlStack.UrlRewriter mUrlRewriter;
private final SSLSocketFactory mSslSocketFactory;
public HurlStack() {
this((HurlStack.UrlRewriter)null);
}
public HurlStack(HurlStack.UrlRewriter urlRewriter) {
this(urlRewriter, (SSLSocketFactory)null);
}
public HurlStack(HurlStack.UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {
this.mUrlRewriter = urlRewriter;
this.mSslSocketFactory = sslSocketFactory;
}
public HttpResponse performRequest(Request> request, Map additionalHeaders) throws IOException, AuthFailureError {
//其他代码
URL parsedUrl = new URL(url);
HttpURLConnection connection = this.openConnection(parsedUrl, request);
Iterator var8 = map.keySet().iterator();
// 其他代码
}
}
第一点,实现上面的HttpStack几口,实现了里面的方法.前面的三个构造方法,最后都是走的第三个构造方法.
我们看到一个很熟悉的 HttpURLConnection,我们知道了,HurlStack内部使用的是HttpURLConnection来实现网络通讯的.
部分源码:
public class HttpClientStack implements HttpStack {
protected final HttpClient mClient;
private static final String HEADER_CONTENT_TYPE = "Content-Type";
public HttpClientStack(HttpClient client) {
this.mClient = client;
}
public HttpResponse performRequest(Request> request, Map additionalHeaders) throws IOException, AuthFailureError {
HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders);
addHeaders(httpRequest, additionalHeaders);
addHeaders(httpRequest, request.getHeaders());
this.onPrepareRequest(httpRequest);
HttpParams httpParams = httpRequest.getParams();
int timeoutMs = request.getTimeoutMs();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);
return this.mClient.execute(httpRequest);
}
//其他代码
}
也是实现了HttpStack,构造方法只有一个,我们看到又一个熟悉的类,HttpClient.
public interface Network {
NetworkResponse performRequest(Request> var1) throws VolleyError;
}
我们看到的是NetWork是一个接口,里面月也有一个类似于HttapStack的方法,performRequest(参数1个);
最终我们获取了RequestQueue,我们看看源码中start()方法.
构造方法三个,我们看使用的这一个;
public RequestQueue(Cache cache, Network network) {
this(cache, network, 4);
}
这个参数4说明一下子,这个是 int threadPoolSize;
调用下面的构造方法:
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
实际上最后走的构造方法三:
public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
this.mSequenceGenerator = new AtomicInteger();
this.mWaitingRequests = new HashMap();
this.mCurrentRequests = new HashSet();
this.mCacheQueue = new PriorityBlockingQueue();
this.mNetworkQueue = new PriorityBlockingQueue();
this.mCache = cache;
this.mNetwork = network;
this.mDispatchers = new NetworkDispatcher[threadPoolSize];
this.mDelivery = delivery;
}
start()方法如下:
public void start() {
this.stop();
this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
this.mCacheDispatcher.start();
for(int i = 0; i < this.mDispatchers.length; ++i) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
this.mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
注意: NetworkDispatcher,CacheDispatcher
分别看看这两个类,在看start()方法.
其他先不管,我们看到这两个类都继承Thread,我们现在来看这个start方法,for循环,我们看到this.mDispatchers;
看RequestQueue的第三个构造方法, this.mDispatchers = new NetworkDispatcher[threadPoolSize];
threadPoolSize这个值等于多少呢,等于4,前面有标注哈!
for循环,循环五次哈,每一次都new NetworkDispatcher,NetworkDispatcher是一个线程,也就是生成了五个线程在后台. 最后都调用了start()来启动了.
CacheDispatcher是缓存线程,NetworkDispatcher是网络请求线程。
mRequestQueue.add(weatherInfoGsonRequest);
我们看add()方法;
部分源码:
public Request add(Request request) {
request.setRequestQueue(this);
Set var2 = this.mCurrentRequests;
synchronized(this.mCurrentRequests) {
this.mCurrentRequests.add(request);
}
request.setSequence(this.getSequenceNumber());
request.addMarker("add-to-queue");
if (!request.shouldCache()) {
this.mNetworkQueue.add(request);
return request;
} else {
Map var7 = this.mWaitingRequests;
synchronized(this.mWaitingRequests) {
String cacheKey = request.getCacheKey();
if (this.mWaitingRequests.containsKey(cacheKey)) {
Queue stagedRequests = (Queue)this.mWaitingRequests.get(cacheKey);
if (stagedRequests == null) {
stagedRequests = new LinkedList();
}
((Queue)stagedRequests).add(request);
this.mWaitingRequests.put(cacheKey, stagedRequests);
if (VolleyLog.DEBUG) {
VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", new Object[]{cacheKey});
}
} else {
this.mWaitingRequests.put(cacheKey, (Object)null);
this.mCacheQueue.add(request);
}
return request;
}
}
}
重点代码:
if (!request.shouldCache()) {
this.mNetworkQueue.add(request);
return request;
}
还有一段:
else {
this.mWaitingRequests.put(cacheKey, (Object)null);
this.mCacheQueue.add(request);
}
会判断当前的请求是否可以缓存,如果不能缓存将这条请求加入网络请求队列,可以缓存的话将这条请求加入缓存队列;看看是否能缓存判断.
request.shouldCache(),点击进入;
再次查看这个变量;
Request的构造方法里面默认是true,也就是可以默认请求都是可以缓存的.
第一步获取 volley.newRequestQueue 这个方法两个,一个context和一个context HttpStack的参数的构造方法,最后走的都是 RequestQueeu(context context, HttpStack stack)方法,
里面的具体就是根据版本 大于9 获取urlStack 小于9,获取9获取的 HttpClientStack;UrlStack的内部是HttpUrl connection实现网络通讯的.
HttpClinetStack内部是HttpClient 实现的网络通讯,选择HttpUrlConnection的原因是在体积更小,可拓展行强.加上sdk在小于9的有bug问题(具体的是…);
获取完stack后,volley内部直接 new RequestQueue,并且start方法;启动了
HttpStack和NetWork都是一个接口,都有一个方法 performReques方法;只不过参数不一样.
我们进入ReQuestQueu源码,看到是,三个构造方法,最后三个都会走一个构造方法,并且指定了线程池size的大小为4; 我们在看start方法,里面重点就是根据线程的大小来for循环,创建 cacheDispatcher(缓存线程)+ NetWorkDispatcher (请求线程);循环一个创建一个NetWorkDispatcher线程,并start(); 后台线程数是5个,注意的cacheDispatcher和NetWorkDispatcher都是继承Thread的;之后步骤就是创建一个 Request添加到 RequesetQueue中,我们看ReQuestQueue的add();
重点就是: 判断线程 shouldcache 是否可以缓存,默认所有线程是可以缓存的,可以缓存添加早cacheQueue中 ,不能添加到NetWorkQueue中.
添加到我们看看这个线程中的run方法,先看CacheDispatcher 中的run();
// 部分源码 也是绝大部分源码
public void run() {
if (DEBUG) {
VolleyLog.v("start new dispatcher", new Object[0]);
}
Process.setThreadPriority(10);
this.mCache.initialize();
while(true) {
while(true) {
while(true) {
while(true) {
try {
while(true) {
final Request request = (Request)this.mCacheQueue.take();
request.addMarker("cache-queue-take");
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
} else {
Entry entry = this.mCache.get(request.getCacheKey());
if (entry == null) {
request.addMarker("cache-miss");
this.mNetworkQueue.put(request);
} else if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
this.mNetworkQueue.put(request);
} else {
request.addMarker("cache-hit");
Response> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
if (entry.refreshNeeded()) {
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
response.intermediate = true;
this.mDelivery.postResponse(request, response, new Runnable() {
public void run() {
try {
CacheDispatcher.this.mNetworkQueue.put(request);
} catch (InterruptedException var2) {
;
}
}
});
} else {
this.mDelivery.postResponse(request, response);
}
}
}
}
} catch (InterruptedException var4) {
if (this.mQuit) {
return;
}
}
}
}
}
}
}
关键代码如下:
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
} else {
Entry entry = this.mCache.get(request.getCacheKey());
if (entry == null) {
request.addMarker("cache-miss");
this.mNetworkQueue.put(request);
} else if (entry.isExpired()) {
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
this.mNetworkQueue.put(request);
}
//我们自己翻译 canceled 是否取消 entry实体 expired 是否过期
if(请求是否取消){
}else{
// 没有 获取缓存
if(缓存==null){
// 添加到网络请求队列中
}else if(是否过期){
// 缓存存在,过期,也添加到网络请求队列中;
}else{
// 缓存存在,没过期 使用这个缓存获取response
// 开始解析这个请求
// 调用postResponse(参数)
}
}
部分源码:
` public void run() {
Process.setThreadPriority(10);
while(true) {
Request request;
while(true) {
try {
request = (Request)this.mQueue.take();
break;
} catch (InterruptedException var4) {
if (this.mQuit) {
return;
}
}
}
try {
request.addMarker("network-queue-take");
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
} else {
if (VERSION.SDK_INT >= 14) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
NetworkResponse networkResponse = this.mNetwork.performRequest(request);
request.addMarker("network-http-complete");
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
} else {
Response> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");
if (request.shouldCache() && response.cacheEntry != null) {
this.mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
request.markDelivered();
this.mDelivery.postResponse(request, response);
}
}
} catch (VolleyError var5) {
this.parseAndDeliverNetworkError(request, var5);
} catch (Exception var6) {
VolleyLog.e(var6, "Unhandled exception %s", new Object[]{var6.toString()});
this.mDelivery.postError(request, new VolleyError(var6));
}
}
}`
while循环,一直在原先,后台线程.
关键代码:
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
} else {
if (VERSION.SDK_INT >= 14) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
NetworkResponse networkResponse = this.mNetwork.performRequest(request);
request.addMarker("network-http-complete");
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
} else {
Response> response = request.parseNetworkResponse(networkResponse);
request.addMarker("network-parse-complete");
if (request.shouldCache() && response.cacheEntry != null) {
this.mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
request.markDelivered();
this.mDelivery.postResponse(request, response);
}
}
简化:
if(关闭){
}else{
//没有关闭
if(大于等于14){
//
}
this.mNetwork.performRequest(request);// 执行请求,获取NetWorkResponse
// this.mDelivery.postResponse(request, response);
}
我们简化后看到, 调用了NetWork的PerformRequest,来执行请求,我们知道在上面说到过NetWork是一个接口,具体的是实现,选择network的perform,右击选择 go to Implementations 看具体的现象,跳转到BasicNetwork,看具体实现.
对NetWork的具体实现:
部分代码:
public NetworkResponse performRequest(Request> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();
while(true) {
HttpResponse httpResponse = null;
byte[] responseContents = null;
HashMap responseHeaders = new HashMap();
try {
Map headers = new HashMap();
this.addCacheHeaders(headers, request.getCacheEntry());
httpResponse = this.mHttpStack.performRequest(request, headers);
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
Map responseHeaders = convertHeaders(httpResponse.getAllHeaders());
if (statusCode == 304) {
return new NetworkResponse(304, request.getCacheEntry().data, responseHeaders, true);
}
byte[] responseContents;
if (httpResponse.getEntity() != null) {
responseContents = this.entityToBytes(httpResponse.getEntity());
} else {
responseContents = new byte[0];
}
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
this.logSlowRequests(requestLifetime, request, responseContents, statusLine);
if (statusCode >= 200 && statusCode <= 299) {
return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
}
throw new IOException();
} catch (SocketTimeoutException var12) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (ConnectTimeoutException var13) {
attemptRetryOnException("connection", request, new TimeoutError());
} catch (MalformedURLException var14) {
throw new RuntimeException("Bad URL " + request.getUrl(), var14);
} catch (IOException var15) {
int statusCode = false;
NetworkResponse networkResponse = null;
if (httpResponse == null) {
throw new NoConnectionError(var15);
}
int statusCode = httpResponse.getStatusLine().getStatusCode();
VolleyLog.e("Unexpected response code %d for %s", new Object[]{statusCode, request.getUrl()});
if (responseContents == null) {
throw new NetworkError(networkResponse);
}
networkResponse = new NetworkResponse(statusCode, (byte[])responseContents, responseHeaders, false);
if (statusCode != 401 && statusCode != 403) {
throw new ServerError(networkResponse);
}
attemptRetryOnException("auth", request, new AuthFailureError(networkResponse));
}
}
}
关键代码: httpResponse = this.mHttpStack.performRequest(request, headers);
我们说过,HttpStack是一个接口,也定义了一个方法performRequest(),只不过参数不一样,我们前面看到这个的子类有UrlStack和HttpClientStack,我们后期主要看UrlStack;
public HttpResponse performRequest(Request> request, Map additionalHeaders) throws IOException, AuthFailureError {
String url = request.getUrl();
HashMap map = new HashMap();
map.putAll(request.getHeaders());
map.putAll(additionalHeaders);
if (this.mUrlRewriter != null) {
String rewritten = this.mUrlRewriter.rewriteUrl(url);
if (rewritten == null) {
throw new IOException("URL blocked by rewriter: " + url);
}
url = rewritten;
}
URL parsedUrl = new URL(url);
HttpURLConnection connection = this.openConnection(parsedUrl, request);
Iterator var8 = map.keySet().iterator();
while(var8.hasNext()) {
String headerName = (String)var8.next();
connection.addRequestProperty(headerName, (String)map.get(headerName));
}
setConnectionParametersForRequest(connection, request);
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
int responseCode = connection.getResponseCode();
if (responseCode == -1) {
throw new IOException("Could not retrieve response code from HttpUrlConnection.");
} else {
StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(), connection.getResponseMessage());
BasicHttpResponse response = new BasicHttpResponse(responseStatus);
response.setEntity(entityFromConnection(connection));
Iterator var12 = connection.getHeaderFields().entrySet().iterator();
while(var12.hasNext()) {
Entry> header = (Entry)var12.next();
if (header.getKey() != null) {
Header h = new BasicHeader((String)header.getKey(), (String)((List)header.getValue()).get(0));
response.addHeader(h);
}
}
return response;
}
}
就是使用HttpUrlConnection来实现网络通讯.执行请求,对这个请求的response进行解析,最后// this.mDelivery.postResponse(request, response);
我们看看这个 his.mDelivery.postResponse(request, response);
实现是在:ExecutorDelivery
部分源码:
public void postResponse(Request> request, Response> response) {
this.postResponse(request, response, (Runnable)null);
}
public void postResponse(Request> request, Response> response, Runnable runnable) {
request.markDelivered();
request.addMarker("post-response");
this.mResponsePoster.execute(new ExecutorDelivery.ResponseDeliveryRunnable(request, response, runnable));
}
我们继续看 ResponseDeliveryRunnable,实现的Runnable
public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
this.mRequest = request;
this.mResponse = response;
this.mRunnable = runnable;
}
public void run() {
if (this.mRequest.isCanceled()) {
this.mRequest.finish("canceled-at-delivery");
} else {
if (this.mResponse.isSuccess()) {
this.mRequest.deliverResponse(this.mResponse.result);
} else {
this.mRequest.deliverError(this.mResponse.error);
}
if (this.mResponse.intermediate) {
this.mRequest.addMarker("intermediate-response");
} else {
this.mRequest.finish("done");
}
if (this.mRunnable != null) {
this.mRunnable.run();
}
}
}
管家代码: this.mRequest.deliverResponse(this.mResponse.result);
其实就是调用了 Request的deliverResponse方法,这个方法就是在自定义Requeset的时候重写的方法,
这个listener