Volley最主要的功能其实就是跟网络打交道,然后从网络中获取相对应的数据,虽然有缓存线程(CacheDispatcher),但是如果缓存中没有对应的记录的话,还是会将其扔到网络队列中,由网络线程(NetworkDispatcher)来干活。
那么就看看NetworkDispatcher都干什么吧,如下:
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- Request<?> request;
- while (true) {
- try {
-
- request = mQueue.take();
- } catch (InterruptedException e) {
-
- if (mQuit) {
- return;
- }
- continue;
- }
-
- try {
- request.addMarker("network-queue-take");
-
-
- if (request.isCanceled()) {
- request.finish("network-discard-cancelled");
- continue;
- }
-
- addTrafficStatsTag(request);
-
-
- NetworkResponse networkResponse = mNetwork.performRequest(request);
- request.addMarker("network-http-complete");
-
-
- if (networkResponse.notModified && request.hasHadResponseDelivered()) {
- request.finish("not-modified");
- continue;
- }
-
-
- 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");
- }
-
-
- request.markDelivered();
- mDelivery.postResponse(request, response);
- } catch (VolleyError volleyError) {
- parseAndDeliverNetworkError(request, volleyError);
- } catch (Exception e) {
- VolleyLog.e(e, "Unhandled exception %s", e.toString());
- mDelivery.postError(request, new VolleyError(e));
- }
- }
- }
网络线程(NetworkDispatcher)主要做了几件事情:
1)调用 mQueue的take()方法从队列中获取请求,如果没有请求,则一直阻塞在那里等待,直到队列中有新的请求到来。
2)判断请求有没有被取消,如果被取消,则重新获取请求。
3)调用Network对象将请求发送到网络中,并返回一个 NetworkResponse对象。
4)调用请求的pareseNetworkResonse方法,将NetworkResponse对象解析成相对应的Response对象。
5)判断请求是否需要缓存,如果需要缓存,则将其Response中cacheEntry对象放到缓存mCache中。
6)调用 mDelivery将Response对象传到主线程中进行UI更新。
另外有一个要注意的就是,在Volley中,默认是有4个网络线程同时在跑的,而对应的缓存线程,则只有一个。
从上面的代码中,可以看到,网络线程其实是调用 Network对象去实现跟网络进行沟通的,而在Volley中,默认的Network实现类,则是BasicNetwork类。
下面我们就看看它的performRequest方法:
- public NetworkResponse performRequest(Request<?> request) throws VolleyError {
- ...
- while (true) {
- HttpResponse httpResponse = null;
- byte[] responseContents = null;
- Map<String, String> responseHeaders = new HashMap<String, String>();
- try {
-
- Map<String, String> headers = new HashMap<String, String>();
- addCacheHeaders(headers, request.getCacheEntry());
- httpResponse = mHttpStack.performRequest(request, headers);
- StatusLine statusLine = httpResponse.getStatusLine();
- int statusCode = statusLine.getStatusCode();
-
- responseHeaders = convertHeaders(httpResponse.getAllHeaders());
-
- if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
- return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
- request.getCacheEntry() == null ? null : request.getCacheEntry().data,
- responseHeaders, true);
- }
-
-
- if (httpResponse.getEntity() != null) {
- responseContents = entityToBytes(httpResponse.getEntity());
- } else {
-
-
- responseContents = new byte[0];
- }
- ...
- return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
- } ...
- } catch (IOException e) {
- ...
- if (responseContents != null) {
- networkResponse = new NetworkResponse(statusCode, responseContents,
- responseHeaders, false);
- if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
- statusCode == HttpStatus.SC_FORBIDDEN) {
- attemptRetryOnException("auth",
- request, new AuthFailureError(networkResponse));
- } else {
- throw new ServerError(networkResponse);
- }
- } else {
- throw new NetworkError(networkResponse);
- }
- }
- }
- }
BasicNetwork做的事情如下:
1)对于已经有缓存的请求,添加其头部信息,如下:
- private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) {
-
- if (entry == null) {
- return;
- }
-
- if (entry.etag != null) {
- headers.put("If-None-Match", entry.etag);
- }
-
- if (entry.serverDate > 0) {
- Date refTime = new Date(entry.serverDate);
- headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
- }
- }
2)调用 HttpStack 对象去网络中获取数据,返回httpResonse 对象。
3)根据状态编码来返回不同的Response对象,如304(未修改)就返回缓存中的数据,如果不是,则根据响应中的数据,重新构造一个NetworkResponse对象。
4)BasicNetwork实现了重试的机制,如果第一次从网络获取失败,默认会重新再尝试一次,如果失败,则会将Error返回,默认的实现类是DefaultRetryPolicy类。
在Network中返回的NetworkResponse对象,会在NetworkDispatcher中由具体的Request(比如ImageRequest,JsonRequest)类来进行解析,再最后返回给UI线程。