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
- Volley源码理解之 一
- Android源码分析之理解Volley
- 理解Volley专题<一>
- Volley源码解析(一)
- Volley源码分析一
- Volley源码解析(一)
- Volley源码分析(一)
- Volley源码解析(一)
- Android Volley完全解析之从源码的角度理解Volley
- Volley学习(一)Android Volley源码解析
- Volley 源码解析(一)
- Volley源码解析(一)
- Volley 源码分析(一)
- Volley源码分析(一)
- Android之Volley 源码解析
- Android部分开源项目源码分析之---Volley源码分析(一)
- Volley完全解析4 从源码角度理解Volley
- Android Volley 带你从源码的角度理解Volley
- JavaBean 用反射自己实现简单内省操作 基础
- CSS规范 - 优化方案
- mysql 数据库字段为 call 数据无法插入
- CSS规范 - 代码格式
- PHPnow开启PHP扩展里openssl支持的方法
- Volley源码理解之 一
- XCode升级之后插件无法使用的解决方案
- CSS规范 - 命名规则
- NOIP2011观光公交
- android-downloader_一个带进度条的下载开源框架源码解析(雷惊风)
- CSS规范 - 分类方法
- PSNR定义与计算
- Boost.Spirit x3学习笔记
- ctemplate简单使用test