关闭

Volley源码理解之 一

标签: androidvolley源码
348人阅读 评论(0) 收藏 举报
分类:

最近项目需要用到volley,觉得有必要读一下源码,于是乎把这几天的理解写出来,希望能帮助到大家的理解。
volley的具体使用可以参考这里写链接内容。由于太懒就直接借鉴网上的教程啦。


Volley类

Volley类主要实现了了一个newRequestQueue方法,在这个方法做了一些初始化工作。

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);//设置缓存路径
        //这里主要是给sdk9以下的网络设置userAgent参数,
        String userAgent = "volley/0";
        try {
            String packageName = context.getPackageName();
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException e) {
        }

        //一般我们会初始化这个方法newRequestQueue(Context context),所以在这里会实例化一个stack,这里SDK9以上使用的是
        //HttpURLConnection,以下用的是HttpClient,具体原因可参考http://blog.csdn.net/guolin_blog/article/details/12452307
        //由于现在的手机基本都是9以上,所以只研究HurlStack
        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;
    }

HurlStack

现在先对HurlStack进行解读,HurlStack类主要实现了一个 performRequest方法,改方法封装了使用HttpURLConnection访问网络获取结果并且封装到HttpResponse中,看来用HttpURLConnection访问网络,但还是对httpclient念念不忘啊

public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        String url = request.getUrl();
        HashMap<String, String> map = new HashMap<String, String>();
        map.putAll(request.getHeaders());
        map.putAll(additionalHeaders);
        if (mUrlRewriter != null) {
            String rewritten = mUrlRewriter.rewriteUrl(url);
            if (rewritten == null) {
                throw new IOException("URL blocked by rewriter: " + url);
            }
            url = rewritten;
        }
        URL parsedUrl = new URL(url);
        //创建一个HttpURLConnection
        HttpURLConnection connection = openConnection(parsedUrl, request);
        //添加http header
        for (String headerName : map.keySet()) {
            connection.addRequestProperty(headerName, map.get(headerName));
        }
        /**设置访问方式,如果为post则在addBodyIfExists添加参数
         *  case Method.GET:
                connection.setRequestMethod("GET");
                break;
            case Method.POST:
                connection.setRequestMethod("POST");
                改方法的实现在下面代码
                addBodyIfExists(connection, request);
                break;
         */
        setConnectionParametersForRequest(connection, request);
        /**
         * 下面的方法都是为了将访问结果封装到httpresponse中
         */
        // Initialize HttpResponse with data from the HttpURLConnection.
        ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
        int responseCode = connection.getResponseCode();
        if (responseCode == -1) {
            // -1 is returned by getResponseCode() if the response code could not be retrieved.
            // Signal to the caller that something was wrong with the connection.
            throw new IOException("Could not retrieve response code from HttpUrlConnection.");
        }
        //封装起始行(‘HTTP/1.1 200 OK’)
        StatusLine responseStatus = new BasicStatusLine(protocolVersion,
                connection.getResponseCode(), connection.getResponseMessage());
        BasicHttpResponse response = new BasicHttpResponse(responseStatus);
        //封装响应主体
        response.setEntity(entityFromConnection(connection));
        //封装响应首部
        for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
            if (header.getKey() != null) {
                Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
                response.addHeader(h);
            }
        }
        return response;
    }
private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
            throws IOException, AuthFailureError {
        byte[] body = request.getBody();
        //post请求需要这些参数
        if (body != null) {
            connection.setDoOutput(true);
            connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(body);
            out.close();
        }
    }

 public byte[] getBody() throws AuthFailureError {
        //直接调用getParams()的值作为post请求的参数,默认返回空,所以只要重写getParams就可以往post添加参数了
        Map<String, String> params = getParams();
        if (params != null && params.size() > 0) {
            return encodeParameters(params, getParamsEncoding());
        }
        return null;
    }

BasicNetwork

BasicNetwork 也主要实现了performRequest方法,将数据解析出来存放到NetworkResponse 类中。它接手HurlStack返回的response并封装

public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();
        while (true) {
            HttpResponse httpResponse = null;
            byte[] responseContents = null;
            Map<String, String> responseHeaders = Collections.emptyMap();

                Map<String, String> headers = new HashMap<String, String>();
                addCacheHeaders(headers, request.getCacheEntry());
                //调用HttpStack.performRequest方法获取httpResponse,并解析它
                httpResponse = mHttpStack.performRequest(request, headers);
                StatusLine statusLine = httpResponse.getStatusLine();
                int statusCode = statusLine.getStatusCode();

                //保存所有首部信息
                responseHeaders = convertHeaders(httpResponse.getAllHeaders());
                //304获取本地缓存
                if (statusCode == HttpStatus.SC_NOT_MODIFIED) {

                    Entry entry = request.getCacheEntry();
                    if (entry == null) {
                        return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null,
                                responseHeaders, true,
                                SystemClock.elapsedRealtime() - requestStart);
                    }

                    //将返回码,返回主体,返回首部,是否304,接受网络响应时间保存到NetworkResponse类中
                    //304是获取的主体是保存在本地的request.getCacheEntry()
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,
                            entry.responseHeaders, true,
                            SystemClock.elapsedRealtime() - requestStart);
                }


                if (httpResponse.getEntity() != null) {
                  responseContents = entityToBytes(httpResponse.getEntity());
                } else {
                  responseContents = new byte[0];
                }


                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;

                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }
                //不是304的时候置为false,获取的主体是从服务器获取的httpResponse.getEntity()
                return new NetworkResponse(statusCode, responseContents, responseHeaders, false,
                        SystemClock.elapsedRealtime() - requestStart);
        }

RequestQueue

接下来就是
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
在volley的newRequestQueue中初始化了RequestQueue,在的构造方法如下

DiskBasedCache使用LinkedHashMap定义了一个LRU的缓存方式,具体可以去了解LinkedHashMap。
RequestQueue的构造方法中定义了一个默认threadPoolSize为4的网络请求线程数组,和一个结果执行类ExecutorDelivery
//实例化ExecutorDelivery,参数是主线程的Looper,这样就可以直接在这个实例化的Handler中更新UI,(Handler,Looper,Message的关系)
public RequestQueue(Cache cache, Network network, int threadPoolSize) {
        this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper()))); 
    }
 public RequestQueue(Cache cache, Network network, int threadPoolSize,
            ResponseDelivery delivery) {
        mCache = cache;
        mNetwork = network;
        mDispatchers = new NetworkDispatcher[threadPoolSize];
        mDelivery = delivery;
    }

ResponseDelivery

ExecutorDelivery构造函数如下,初始化mResponsePoster ,后面可直接调用mResponsePoster.execute方法执行Runnable 
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);
            }
        };
    }

该类实现的ResponseDelivery接口的postResponse方法,当调用这个方法时就可以直接在主线程执行Runnable

public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
        //标记已经执行了请求
        request.markDelivered();
        //直接执行封装的ResponseDeliveryRunnable
        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
    }
//ResponseDeliveryRunnable线程 执行的时候调用run()
//这个类主要是处理请求结果的时候才会执行的,因为RequestQueue构造方法中实现了,所以就先讲它了
private class ResponseDeliveryRunnable implements Runnable {
        private final Request mRequest;
        private final Response mResponse;
        private final Runnable mRunnable;

        public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
            mRequest = request;
            mResponse = response;
            mRunnable = runnable;
        }

        @SuppressWarnings("unchecked")
        @Override
        public void run() {

            //判断网络响应是否成功,成功的话回调deliverResponse,错误的话回调deliverError方法
            if (mResponse.isSuccess()) {
                mRequest.deliverResponse(mResponse.result);
            } else {
                mRequest.deliverError(mResponse.error);
            }

            // 不为空的话执行它
            if (mRunnable != null) {
                mRunnable.run();
            }
       }
    }

RequestQueue初始化之后,调用run()执行它,

//然后启动一个缓存调度线程,四个网络请求线程(默认值为4,threadPoolSize)
//这些线程就会一直循环的获取队列信息,
//启动了这么多线程是要干一场的节奏,所以我们调用Volley.newRequestQueue 方法时,用上单例,才是很好的初始化方式。
public void start() {
        //执行该方法后,调用该方法,首先停止所有下面的线程然后在启动一次,
        stop();  
        // 缓存调度线程
        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();
        }
    }
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:41696次
    • 积分:601
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:0篇
    • 评论:36条
    最新评论