Volley网络请求框架分析

本文代码省略了许多个人认为不重要的内容,具体请参考volley源码

volley的入口在Volley.java的newRequestQueue方法中
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);

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

        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                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;
    }
上面的代码最主要的内容是在SDK>9的时候使用HttpUrlconnection,其他时候使用HttpClient(BTW: 据说HttpClient在android6.0上已经不能使用了)
最重要的代码是queue.start()
queue.start();   //初始化,开始接收网络请求
    mCacheDispatcher.start();
        mCache.initialize();   //缓存初始化
        while(true)
            if (request.isCanceled()) {    //请求是否取消
                request.finish("cache-discard-canceled");  //执行finish
            }
            Cache.Entry entry = mCache.get(request.getCacheKey());   //尝试从缓存中获取
            if (entry == null) {
                mNetworkQueue.put(request);   //如果缓存中没有,添加到网络队列
            }
            if (entry.isExpired()) {        //检查缓存是否过期
                request.setCacheEntry(entry);       //缓存已经过期,重用缓存实例,将缓存加入到网络队列中
                mNetworkQueue.put(request);
            }
            //此时缓存已经命中,根据volley支持的几种网络请求(图片,json,string等)解析网络应答
            Response response = request.parseNetworkResponse(
                new NetworkResponse(entry.data, entry.responseHeaders));
            if (!entry.refreshNeeded()) { //根据httpHeader中的softTtl判断缓存是否需要刷新
            	//分配器交付此次网络应答
            	mDelivery.postResponse(request, response);
            } else {
            	//根据softTtl设置来说,缓存已经过期,依旧可以交付此次网络应答,不过需要后台刷新此次请求
            	request.setCacheEntry(entry);
            	response.intermediate = true;
            	mDelivery.postResponse(request, response, new Runnable() {   //此次网络应答已经过期,虽然可以交付,但是需要进行刷新操作
                    @Override
                    public void run() {
                        mNetworkQueue.put(request);
                    }
                });
            }
    networkDispatcher.start();
        while (true)
            request = mQueue.take();
                if (request.isCanceled()) {  //请求已经取消
                request.finish("network-discard-cancelled");
            }
            addTrafficStatsTag(request);  //统计流量使用
            NetworkResponse networkResponse = mNetwork.performRequest(request);  //执行网络请求
            	while (true) 
            		Map responseHeaders = Collections.emptyMap(); //httpHeader
            		Map headers = new HashMap(); //cacheHeader
            		httpResponse = mHttpStack.performRequest(request, headers);  //网络请求核心部分,httpstack需要实现performRequest用于请求http应答
            		int statusCode = statusLine.getStatusCode(); //获取网络状态码
            		responseHeaders = convertHeaders(httpResponse.getAllHeaders()); //获取httpHeader
            		if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
            			entry.responseHeaders.putAll(responseHeaders); //更新缓存的httpHeader
            			return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,  //返回网络应答
                            entry.responseHeaders, true,
                            SystemClock.elapsedRealtime() - requestStart);
            		}
            		//处理部分网络entity为空的情况
            		if (httpResponse.getEntity() != null) {
	                  	responseContents = entityToBytes(httpResponse.getEntity());
	                } else {
						responseContents = new byte[0];
	                }
	                //处理部分网络速度过慢问题
	                logSlowRequests(requestLifetime, request, responseContents, statusLine);
	                if (statusCode < 200 || statusCode > 299) { //在ioException中处理网络异常情况
	                    throw new IOException();
	                }
	                return new NetworkResponse(statusCode, responseContents, responseHeaders, false, //返回网络应答
                        SystemClock.elapsedRealtime() - requestStart); 
            if (networkResponse.notModified && request.hasHadResponseDelivered()) { //返回304或者网络请求已经被处理
                request.finish("not-modified");
            }
            Response response = request.parseNetworkResponse(networkResponse); //解析网络应答
            if (request.shouldCache() && response.cacheEntry != null) { //缓存网络应答
                mCache.put(request.getCacheKey(), response.cacheEntry);
            }
            request.markDelivered(); //标记请求已经被处理
        	mDelivery.postResponse(request, response); //分配器交付此次网络应答

在start方法中默认创建了一个缓存线程和四个网络线程,分别对应着一个缓存队列一个网络队列,缓存线程和网络线程不停的从这两个队列中获取request并执行,那么这两个队列中的request从何而来的呢,答案是queue.add
queue.add();
    mCurrentRequests.add(request);   //将请求添加到请求队列中,用于在cancel中取消
    if (!request.shouldCache()) {    //如果不需要缓存直接加入网络队列中,否则加入缓存队列
        mNetworkQueue.add(request);
        return request;
    }
    if (mWaitingRequests.containsKey(cacheKey)) {   //如果等待队列中包含缓存的key,更新请求
    	Queue> stagedRequests = mWaitingRequests.get(cacheKey);  
    	stagedRequests.add(request);
        mWaitingRequests.put(cacheKey, stagedRequests);
    } else {
    	mWaitingRequests.put(cacheKey, null);
        mCacheQueue.add(request);
    }

从add方法中可以看出除非request设置了不需要缓存,默认都会将request添加到缓存队列中去,然后由mCacheDispatcher来做下一步的处理

未完待续。。。
 
  

你可能感兴趣的:(网络开发)