跟随郭霖学volley源码

有了前面的velley的使用和学习笔记,今天来学习volley源码

我们就是从使用volley的三部曲来分析;

1.获取RequestQueue的源码流程分析

第一步;获取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源码.

HttpStack

源码:

public interface HttpStack {
HttpResponse performRequest(Request<?> var1, Map<String, String> var2) throws IOException, AuthFailureError;
}

我们看到HttpStack是一个接口,里面只有一个performRequest(参数1,参数2);

我们记住这个方法就行,后面根据接口实现来看.

HurlStack

部分源码:

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<String, String> additionalHeaders) throws IOException, AuthFailureError {
	//其他代码
	
	URL parsedUrl = new URL(url);
    HttpURLConnection connection = this.openConnection(parsedUrl, request);
    Iterator var8 = map.keySet().iterator();

	// 其他代码
	}
}

第一点,实现上面的HttpStack几口,实现了里面的方法.前面的三个构造方法,最后都是走的第三个构造方法.

我们看到一个很熟悉的 HttpURLConnection,我们知道了,HurlStack内部使用的是HttpURLConnection来实现网络通讯的.

HttpClientStack

部分源码:

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<String, String> 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.

NetWork源码

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是网络请求线程。

第二部就是创建Request

将创建完成的Request添加到RequestQueue中

 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<Request> 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源码分析耽搁几天了,复习

第一步获取 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();

先看CacheDispatcher部分源码

// 部分源码 也是绝大部分源码
 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(参数)
					}

}

NetWorkDispatcher源码

部分源码:

` 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,看具体实现.

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<String, String> headers = new HashMap();
            this.addCacheHeaders(headers, request.getCacheEntry());
            httpResponse = this.mHttpStack.performRequest(request, headers);
            StatusLine statusLine = httpResponse.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            Map<String, String> 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<String, String> additionalHeaders) 					throws IOException, AuthFailureError {
    String url = request.getUrl();
    HashMap<String, String> 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<String, List<String>> 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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值