Volley源码理解之 一

来源:互联网 发布:北航软件学院研究生院 编辑:程序博客网 时间:2024/05/17 18:17

最近项目需要用到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
原创粉丝点击