Android Volley 源码总结

主要参考: http://blog.csdn.net/guolin_blog/article/details/17656437
工作流程图:

Android Volley 源码总结_第1张图片
volley_architecture.png

"
其中蓝色部分代表主线程,绿色部分代表缓存线程,橙色部分代表网络线程。我们在主线程中调用RequestQueue的add()方法来添加一条网络请求,这条请求会先被加入到缓存队列当中,如果发现可以找到相应的缓存结果就直接读取缓存并解析,然后回调给主线程。如果在缓存中没有找到结果,则将这条请求加入到网络请求队列中,然后处理发送HTTP请求,解析响应结果,写入缓存,并回调主线程。
"

这里总结几个技术要点:

Gingerbread之前, 底层网络请求的实现使用HttpClient, Gingerbread之后, 底层实现就开始使用HttpUrlConnection了, 因为Gingerbread之前的HttpUrlConnection不稳定.

//Volley.java
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        //File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
        File cacheDir = new File(FeatureConfig.ROOT_CACHE_PATH_BASE, DEFAULT_CACHE_DIR);

        String userAgent = "volley/0";
        try {
            String packageName = context.getPackageName();
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (Throwable e) {
        }

        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                //use httpUrlConnection
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        Network network = new BasicNetwork(stack);

        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();

        return queue;
    }

RequestQueue.java
    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();
//这里启动一个Cache线程, 不断的从RequestQueue队列里取元素.
        // Create network dispatchers (and corresponding threads) up to the pool size.
//默认创建4个Network线程, 不断的在自己的队列里取元素, 执行真正的网络请求.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }

CacheDispatcher是一个Thread, 它的run()方法, 是个死循环.

public class CacheDispatcher extends Thread {

    @Override
    public void run() {
        if (DEBUG) VolleyLog.v("start new dispatcher");
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        // Make a blocking call to initialize the cache.
        mCache.initialize();

        while (true) {
            try {
                // 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");

                // If the request has been canceled, don't bother dispatching it.
                if (request.isCanceled()) {
                    request.finish("cache-discard-canceled");
                    continue;
                }

                // 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;
                }
...

                // We have a cache hit; parse its data for delivery back to the request.
                request.addMarker("cache-hit");
                Response response = null;
                try {
                    response = request.parseNetworkResponse(
                            new NetworkResponse(entry.data, entry.responseHeaders));
                } catch (Exception e) {
                    mDelivery.postError(request, new ParseError(e));
                    continue;
                } catch (Error error) {
                    mDelivery.postError(request, new ParseError(error));
                    continue;
                }
                request.addMarker("cache-hit-parsed");

                if (!entry.refreshNeeded()) {
                    // Completely unexpired cache hit. Just deliver the response.
                    mDelivery.postResponse(request, response);
                } else {
                    // Soft-expired cache hit. We can deliver the cached response,
                    // but we need to also send the request to the network for
                    // refreshing.
                    request.addMarker("cache-hit-refresh-needed");
                    request.setCacheEntry(entry);

                    // Mark the response as intermediate.
                    response.intermediate = true;

                    // Post the intermediate response back to the user and have
                    // the delivery then forward the request along to the network.
                    mDelivery.postResponse(request, response, new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mNetworkQueue.put(request);
                            } catch (InterruptedException e) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }

            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            } catch (OutOfMemoryError error) {
                if (mQuit) {
                    return;
                }
                continue;
            }
        }
    }

NetworkDispatcher也是一个Thread, 它的run()方法, 是个死循环.

public class NetworkDispatcher extends Thread {
public void run() {
    while(true) {
        request = mQueue.take(); //阻塞在这里
        NetworkResponse networkResponse = mNetwork.performRequest(request);

        Response response = request.parseNetworkResponse(networkResponse);

                if (request.shouldCache() && response.cacheEntry != null) {
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }
    }   
}
Volley的总体框架还是非常的清晰的.

========DONE=========

你可能感兴趣的:(Android Volley 源码总结)