美文网首页
Volley缓存框架

Volley缓存框架

作者: 左上偏右 | 来源:发表于2017-02-18 19:51 被阅读60次

    Volley 的主要特点

    (1). 扩展性强。Volley 中大多是基于接口的设计,可配置性强。
    (2). 一定程度符合 Http 规范,包括返回 ResponseCode(2xx、3xx、4xx、5xx)的处理,请求头的处理,缓存机制的支持等。并支持重试及优先级定义。
    (3). 默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现,这两者的区别及优劣在4.2.1 Volley中具体介绍。
    (4). 提供简便的图片加载工具。

    整体框架

    1、设计图

    总体设计图总体设计图

    上面是 Volley 的总体设计图,主要是通过两种Dispatch Thread
    不断从RequestQueue中取出请求,根据是否已缓存调用Cache
    Network这两类数据获取接口之一,从内存缓存或是服务器取得请求的数据,然后交由ResponseDelivery去做结果分发及回调处理。

    1、初始化

    Volley类中newRequestQueue初始化部分。

     public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
            File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
            if (stack == null) {
                if (Build.VERSION.SDK_INT >= 9) {
                    stack = new HurlStack();
                } else {
                    stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
                }
            }
    
            Network network = new BasicNetwork(stack);
    
            RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
            queue.start();
    
            return queue;
        }
    
    
    • 1.1 选择网络请求API
      网络请求(API Level >= 9) 基于 HttpURLConnection 的 HurlStack,当其小于 9,采用基于 HttpClient 的 HttpClientStack。这两个都是实现了HttpStack,它的功能是完成网络请求并返回HttpResponse类。
    public interface HttpStack {
        /**
         * Performs an HTTP request with the given parameters.
         * @param request the request to perform
         * @param additionalHeaders additional headers to be sent together with
         *         {@link Request#getHeaders()}
         * @return the HTTP response
         */
        public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError;
    
    }
    
    • 1.2 解析网络响应
      在BasicNetwork的performRequest(Request<?> request)方法中,获取HttpResponse对象,解析出响应码、响应内容、响应头等信息,之后将其封装成NetworkResponse对象。
      
    public NetworkResponse performRequest(Request<?> request){
        HttpResponse httpResponse = null;
        byte[] responseContents = null;
        Map<String, String> responseHeaders = new HashMap<String, String>();
        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());
        responseContents = entityToBytes(httpResponse.getEntity());
      
        return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
    }
    
    
    • 1.3 任务调度
      Volley 框架的核心类,将请求 Request 加入到一个运行的RequestQueue中,来完成请求操作。
      (1). 主要成员变量
      RequestQueue 中维护了两个基于优先级的 Request 队列,缓存请求队列和网络请求队列。
      放在缓存请求队列中的 Request,将通过缓存获取数据;放在网络请求队列中的 Request,将通过网络获取数据。
      PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<?>>(); PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<Request<?>>();
      维护了一个正在进行中,尚未完成的请求集合。
      private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
      维护了一个等待请求的集合,如果一个请求正在被处理并且可以被缓存,后续的相同 url 的请求,将进入此等待队列。
      private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();

    (2). 启动队列
    创建出 RequestQueue 以后,调用 start 方法,启动队列。

    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }
    

    NetworkDispatcher是一个线程类,采用的是RequestQueue的mNetworkQueue对列作为阻塞对列。在run方法里面不断从mNetworkQueue中取任务,并调用mNetwork.performRequest进行执行,将返回的网络信息交由ResponseDelivery处理。

    
    public class NetworkDispatcher extends Thread {
        private final BlockingQueue<Request<?>> mQueue;
        private final ResponseDelivery mDelivery;
        /** Used for telling us to die. */
        private volatile boolean mQuit = false;
    
        /**
         * 一旦调用quit方法,mQuit为true,会发生InterruptedException异常,就会在run方法中被拦截到,
           由于mQuit是线程间可见,所以当前线程就退出了。
         */
        public void quit() {
            mQuit = true;
            interrupt();
        }
    
        @Override
        public void run() {
            Request<?> request;
            while (true) {
                try {
                    // Take a request from the queue.
                    request = mQueue.take();
                } catch (InterruptedException e) {
                    if (mQuit) {
                        return;
                    }
                    continue;
                }
    
                NetworkResponse networkResponse = mNetwork.performRequest(request);
       
                // Parse the response here on the worker thread.
                Response<?> response = request.parseNetworkResponse(networkResponse);
                mDelivery.postResponse(request, response);
    
            }
        }
    }
    

    2、任务添加

    通过请求队列中的add方法进行添加,简单点就是有缓存请求,就进行缓存任务调度,否则就使用网络任务调度(NetworkDispatcher)。

    3、缓存

    Volley 构建了一套相对完整的符合 Http 语义的缓存机制。
    优点和特点
    (1). 根据Cache-Control和Expires首部来计算缓存的过期时间。如果两个首部都存在情况下,以Cache-Control为准。
    (2). 利用If-None-Match和If-Modified-Since对过期缓存或者不新鲜缓存,进行请求再验证,并处理 304 响应,更新缓存。
    (3). 默认的缓存实现,将缓存以文件的形式存储在 Disk,程序退出后不会丢失。

    4、响应处理

    通过handler进行数据在主线程显示,数据处理使用的是ExecutorDelivery。

        public ExecutorDelivery(final Handler handler) {
            // Make an Executor that just wraps the handler.
            mResponsePoster = new Executor() {
                @Override
                public void execute(Runnable command) {
                    handler.post(command);
                }
            };
        }
    

    相关文章

      网友评论

          本文标题:Volley缓存框架

          本文链接:https://www.haomeiwen.com/subject/wzorwttx.html