Android网络框架volley学习(七)调度器NetworkDispatcher简析

前一篇《Android网络框架volley学习(六)调度器CacheDispatcher简析》了解了关于缓存线程调度CacheDispatcher的工作原理,它里面会判断缓存是否存在、是否过期以及是否需要刷新等操作,如果不满足的话则需要加入到网络请求队列,从而让NetworkDispatcher去处理它。本篇我们继续来学习NetworkDispatcher实现过程,看看网络线程是如何处理请求的?

NetworkDispatcher

同样的,我们首先了解一下它的内部成员变量。

/** 请求队列 */
    private final BlockingQueue> mQueue;
    /** 执行网络请求的接口 */
    private final Network mNetwork;
    /** 缓存类接口 */
    private final Cache mCache;
    /** 结果分发 */
    private final ResponseDelivery mDelivery;

接着我们看下它的初始化过程,也就是构造函数。

 public NetworkDispatcher(BlockingQueue<Request> queue,
            Network network, Cache cache, ResponseDelivery delivery) {
        mQueue = queue;
        mNetwork = network;
        mCache = cache;
        mDelivery = delivery;
    }

很简单,从前面我们得知,NetworkDispatcher其实也是一个线程,那么我们来看下它的run方法。

 @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        while (true) {
            try {
                processRequest();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
            }
        }
    }

跟CacheDispatcher一样的逻辑,接着查看processRequest方法内部实现细节,由于这个方法实现过程代码比较长,我们一步一步进行分析。

  Request request = mQueue.take();
   if (request.isCanceled()) {
                request.finish("network-discard-cancelled");
                request.notifyListenerResponseNotUsable();
                return;
   }

同样的,首先从网络请求队列中取出一条请求,判断它是否取消了,接着往下看。

 // Perform the network request.
 NetworkResponse networkResponse = mNetwork.performRequest(request);

执行了网络请求,然后解析网络请求结果到response

//判断是否是304(表示资源没有修改过)
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                request.finish("not-modified");
                request.notifyListenerResponseNotUsable();
                return;
            }

            // Parse the response here on the worker thread.
            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");
            }

            // Post the response back.
            request.markDelivered();
            mDelivery.postResponse(request, response);
            request.notifyListenerResponseReceived(response);

首先判断这个请求结果是否应该缓存,同时分发这个网络请求结果出去。到这里NetworkDispatcher都讲完了,但是,是不是一脸懵逼?讲的啥?里面还有很多东西没有讲到,我们接着分析。

执行网络请求

上面有行代码时执行网络请求的,

NetworkResponse networkResponse = mNetwork.performRequest(request);

具体是如何实现这个请求的呢?通过performRequest,它是

public interface Network {
    NetworkResponse performRequest(Request request) throws VolleyError;
}

它是一个接口,我们需要知道它的实现类,我们通过查看volley的源码可以知道,它的实现类是BasicNetwork,接下来我们分析一下它的实现过程。

纵观的源码,我们可以看到其中有个成员变量

/**
     * @deprecated Should never have been exposed in the API. This field may be removed in a future
     *             release of Volley.
     */
    @Deprecated
    protected final HttpStack mHttpStack;

其实,HttpStack mHttpStack是实际的网络请求类,进去可以看到它是一个接口,它的实现类有两个

  1. HttpClientStack,基于Apache的HttpClient请求方式
  2. HurlStack,基于Java的HttpURLConnection请求方式

从《Android网络框架volley学习(三)底层网络请求分析》我们可以了解到网络请求方式有两种,根据api是否大于9来判断使用哪种方式。

我们接着分析performRequest方法,

httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);
                int statusCode = httpResponse.getStatusCode();

                responseHeaders = httpResponse.getHeaders();
                // 首先判断请求资源是否被修改过
                if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
                    Entry entry = request.getCacheEntry();
                    if (entry == null) {
                        return new NetworkResponse(HttpURLConnection.HTTP_NOT_MODIFIED, null, true,
                                SystemClock.elapsedRealtime() - requestStart, responseHeaders);
                    }
                    // Combine cached and response headers so the response will be complete.
                    List<Header> combinedHeaders = combineHeaders(responseHeaders, entry);
                    return new NetworkResponse(HttpURLConnection.HTTP_NOT_MODIFIED, entry.data,
                            true, SystemClock.elapsedRealtime() - requestStart, combinedHeaders);
                }

首先判断请求的内容是否被修改过,如果没有被修改过,再根据缓存中是否存在该结果,包装返回NetworkResponse。如果已经修改过的话,则获取请求结果,再次包装返回请求结果。

// Some responses such as 204s do not have content.  We must check.
                InputStream inputStream = httpResponse.getContent();
                if (inputStream != null) {
                  responseContents =
                          inputStreamToBytes(inputStream, httpResponse.getContentLength());
                } else {
                  // Add 0 byte response as a way of honestly representing a
                  // no-content request.
                  responseContents = new byte[0];
                }

                // if the request is slow, log it.
                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                logSlowRequests(requestLifetime, request, responseContents, statusCode);

                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }
                return new NetworkResponse(statusCode, responseContents, false,
                        SystemClock.elapsedRealtime() - requestStart, responseHeaders);

如果期间出错的话,则需要根据code来进行分别处理,包括


int statusCode;
                if (httpResponse != null) {
                    statusCode = httpResponse.getStatusCode();
                } else {
                    //网络有问题
                    throw new NoConnectionError(e);
                }
                VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                NetworkResponse networkResponse;
                if (responseContents != null) {
                    networkResponse = new NetworkResponse(statusCode, responseContents, false,
                            SystemClock.elapsedRealtime() - requestStart, responseHeaders);
                    if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED ||
                            statusCode == HttpURLConnection.HTTP_FORBIDDEN) {
                        attemptRetryOnException("auth",
                                request, new AuthFailureError(networkResponse));
                    } else if (statusCode >= 400 && statusCode <= 499) {
                        // Don't retry other client errors.
                        throw new ClientError(networkResponse);
                    } else if (statusCode >= 500 && statusCode <= 599) {
                        if (request.shouldRetryServerErrors()) {
                            attemptRetryOnException("server",
                                    request, new ServerError(networkResponse));
                        } else {
                            throw new ServerError(networkResponse);
                        }
                    } else {
                        // 3xx? No reason to retry.
                        throw new ServerError(networkResponse);
                    }
                } else {
                    attemptRetryOnException("network", request, new NetworkError());
                }
  1. 如果根本就没有响应内容httpResponse==null,说明网络连接有问题(也就是说手机没有联网),自己抛出异常结束
  2. 302,301错误,说明资源被重定向,做简单的记录
  3. 401,403错误,身份验证错误,重试
  4. 302,301错误,重试

回顾一下,总结流程。

Android网络框架volley学习(七)调度器NetworkDispatcher简析_第1张图片

图片来自于Volley 源码解析

你可能感兴趣的:(Android网络框架volley学习(七)调度器NetworkDispatcher简析)