Volley源码个人分析

一直看源码也是记不住,总是忘记,希望通过博客可以给自己留存一些记忆。

我从入口开始分析,创建一个请求队列,通过Volley的静态方法newRequestQueue新建,然后将请求添加至请求队列即可。

RequestQueue mRequestQueue = Volley.newRequestQueue(context);
mRequestQueue.add(request);

可以通过mRequestQueue的cancelAll方法取消所有TAG请求。

 @Override
    protected void onDestroy() {
        super.onDestroy();
        mRequestQueue.cancelAll(TAG);
    }

接着用一个最简单的请求方式,作为示例看一下请求的参数

StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
            // TODO
                Log.e(TAG, response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            // TODO
                error.printStackTrace();
            }
        });

第一个参数,是一个请求方式,一共有GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH八种方式。
第二个参数,是请求的网络地址url。
第三个参数,是请求返回的响应结果的回调。
第四个参数,是请求返回的错误响应的回调。

以上是一个大概的使用过程,通过这个过程进行分析。

首先,请求队列的创建调用了Volley的newRequestQueue静态方法,跟进去之后发现最终调用了一个含有多个参数的newRequestQueue静态方法。

RequestQueue queue = new RequestQueue(cache==null?new DiskBasedCache(cacheDir):cache, network);
queue.start();

这个方法里new出一个请求队列,请求队列的构造方法需要两个参数,一个缓存,一个网络任务。构造方法没什么说可说的了,就是初始化一些成员变量。创建队列的目的是为了处理请求,所以调用了start方法。

    /**
     * Starts the dispatchers in this queue.
     */
    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();

        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }

start方法里很简单,是新建了一个调度缓存的线程和一个调度网络任务的线程数组,并将所有线程调用start方法启动。接下来,就要去看看线程里的run方法了。
先看看CacheDispatcher的run方法,去除掉我认为不影响流程的代码,剩余的部分就是说,不断的从缓存队列里取任务请求。如果缓存中没有或者已经过期了,就将请求添加至网络请求队列。最后如果缓存中存在的话,就去处理响应结果并解析。


    @Override
    public void run() {

        ······

        while (true) {

                // Get a request from the cache triage queue, blocking until
                // at least one is available.
                final Request<?> request = mCacheQueue.take();
                request.addMarker("cache-queue-take");

                ···

                // Attempt to retrieve this item from cache.
                Cache.Entry entry = mCache.get(request.getCacheKey());
                if (entry == null) {
                    request.addMarker("cache-miss");
                    // Cache miss; send off to the network dispatcher.
                    mNetworkQueue.put(request);
                    continue;
                }

                // If it is completely expired, just send it to the network.
                if (entry.isExpired()) {
                    request.addMarker("cache-hit-expired");
                    request.setCacheEntry(entry);
                    mNetworkQueue.put(request);
                    continue;
                }

                // We have a cache hit; parse its data for delivery back to the request.
                request.addMarker("cache-hit");
                Response<?> response = request.parseNetworkResponse(
                        new NetworkResponse(entry.data, entry.responseHeaders));
                request.addMarker("cache-hit-parsed");

                ···

        }
    }

再看看NetworkDispatcher的run方法,也是有个while死循环,不断的从请求队列里取任务请求。然后通过Network的performRequest方法处理请求,返回响应结果。然后对响应结果进行解析,最后,判断一下是否添加至缓存中,若条件满足,则将请求添加至缓存,方便下次进行快速读取。


    @Override
    public void run() {

        while (true) {

            Request<?> request;

                // Take a request from the queue.
                request = mQueue.take();

                ······

                // Perform the network request.
                NetworkResponse networkResponse = mNetwork.performRequest(request);
                request.addMarker("network-http-complete");

                ······

                // Parse the response here on the worker thread.
                Response<?> response = request.parseNetworkResponse(networkResponse);
                request.addMarker("network-parse-complete");

                // Write to cache if applicable.
                // TODO: Only update cache metadata instead of entire record for 304s.
                if (request.shouldCache() && response.cacheEntry != null) {
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }
            ···
        }
    }

若问请求哪里来?答:通过请求队列的add方法添加。就是最前面提到的mRequestQueue.add(request);

以上就是Volley源码阅读的大概一个过程,无需在意太多的细节,这是我总结出的阅读源码的经验。当然,经验有限,目前也只能写成这样。

在前进的道路上,跟随一些大神的脚步是必不可免的。为了加强理解,更多细节可以看看Volley源码解析

发布了28 篇原创文章 · 获赞 27 · 访问量 13万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章