我们先来Volley请求网络的代码,StringRequest为例:
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(getStringRequest());
public StringRequest getStringRequest() {return new StringRequest("https://suggest.taobao.com/sug?code=utf-8&q=beizi",new Response.Listener<String>() {@Overridepublic void onResponse(String response) {Log.e(getClass().getName(), response);}},new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {Log.e(getClass().getName(), error.getMessage());}});
}
public class StringRequest extends Request<String> {private Listener<String> mListener;public StringRequest(int method, String url, Listener<String> listener,ErrorListener errorListener) {super(method, url, errorListener);mListener = listener;}...@Overrideprotected void deliverResponse(String response) {if (mListener != null) {mListener.onResponse(response);}}@Overrideprotected Response<String> parseNetworkResponse(NetworkResponse response) {String parsed;try {parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));} catch (UnsupportedEncodingException e) {parsed = new String(response.data);}return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));}
}1.RequestQueue
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {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) {}/*** 根据不同的系统版本号实例化不同的请求类,如果版本号小于9,用HttpClient* 如果版本号大于9,用HttpUrlConnection*/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.htmlstack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));}}//把实例化的stack传递进BasicNetwork,实例化NetworkNetwork network = new BasicNetwork(stack);RequestQueue queue;if (maxDiskCacheBytes <= -1){// No maximum size specified//实例化RequestQueue类 queue = new RequestQueue(new DiskBasedCache(cacheDir), network);}else {// Disk cache size specifiedqueue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);}//调用RequestQueue的start()方法queue.start();return queue;
}
Queue.start源码如下:
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();// Create network dispatchers (and corresponding threads) up to the pool size.for (int i = 0; i < mDispatchers.length; i++) {NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,mCache, mDelivery);mDispatchers[i] = networkDispatcher;networkDispatcher.start();}}2.CacheDispatcher类继承自Thread,接着调用了它的start()方法,开始了一条新的缓存线程。接着是一个for循环,根据设置的mDispatchers数组大小来开启多个网络请求线程,默认是4条网络请求线程。到目前为止,Volley.newRequestQueue()方法完成了,即我们的网络请求第一步,建立请求队列完成。建立请求队列所做的工作是,创建文件缓存(默认),实例化BasicNetwork,实例化Delivery用于发送线程请求,创建一条缓存线程和四条网络请求线程(默认)并运行。CacheDispatcher的run方法如下:
@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();Request<?> request;while (true) {// release previous request object to avoid leaking request object when mQueue is drained.request = null;try {//获取缓存队列中的一个请求.request = mCacheQueue.take();} catch (InterruptedException e) {// We may have been interrupted because it was time to quit.if (mQuit) {return;}continue;}try {request.addMarker("cache-queue-take");// 如果请求取消就停止.if (request.isCanceled()) {request.finish("cache-discard-canceled");continue;}// 查看是否有缓存响应Cache.Entry entry = mCache.get(request.getCacheKey());if (entry == null) {request.addMarker("cache-miss");//如果缓存响应为空就加入队列mNetworkQueue.put(request);continue;}// 判断缓存响应是否过期if (entry.isExpired()) {request.addMarker("cache-hit-expired");request.setCacheEntry(entry);mNetworkQueue.put(request);continue;}// We have a cache hit; parse its data for delivery back to the request.request.addMarker("cache-hit");// 对数据进行解析回调给主线程Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));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.final Request<?> finalRequest = request;mDelivery.postResponse(request, response, new Runnable() {@Overridepublic void run() {try {mNetworkQueue.put(finalRequest);} catch (InterruptedException e) {// Not much we can do about this.}}});}} catch (Exception e) {VolleyLog.e(e, "Unhandled exception %s", e.toString());}}
}public <T> Request<T> add(Request<T> request) {// Tag the request as belonging to this queue and add it to the set of current requests.//标记当前请求,表示这个请求由当前RequestQueue处理request.setRequestQueue(this);synchronized (mCurrentRequests) {mCurrentRequests.add(request);}// Process requests in the order they are added.//获得当前请求的序号request.setSequence(getSequenceNumber());request.addMarker("add-to-queue");// If the request is uncacheable, skip the cache queue and go straight to the network.//如果请求不能缓存,直接添加到网络请求队列,默认是可以缓存if (!request.shouldCache()) {mNetworkQueue.add(request);return request;}// Insert request into stage if there's already a request with the same cache key in flight.// 锁定当前代码块,只能一条线程执行synchronized (mWaitingRequests) {String cacheKey = request.getCacheKey();//是否有相同请求正在处理if (mWaitingRequests.containsKey(cacheKey)) {// There is already a request in flight. Queue up.//如果有相同请求正在处理,那么把这个请求放进mWaitingRequest中,等待。Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);if (stagedRequests == null) {stagedRequests = new LinkedList<Request<?>>();}stagedRequests.add(request);mWaitingRequests.put(cacheKey, stagedRequests);if (VolleyLog.DEBUG) {VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);}} else {// Insert 'null' queue for this cacheKey, indicating there is now a request in// flight.//没有相同的请求,那么把请求放进mWaitingRequests中,同时也放进mCacheQueue缓存队列中//这代表这个请求已经开始在缓存线程中运行了mWaitingRequests.put(cacheKey, null);mCacheQueue.add(request);}return request;}
}@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();Request<?> request;while (true) {// release previous request object to avoid leaking request object when mQueue is drained.request = null;try {// Take a request from the queue.request = mCacheQueue.take();} catch (InterruptedException e) {// We may have been interrupted because it was time to quit.if (mQuit) {return;}continue;}try {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;}// If it is completely expired, just send it to the network.if (entry.isExpired()) {request.addMarker("cache-hit-expired");request.setCacheEntry(entry);mNetworkQueue.put(request);continue;}// We have a cache hit; parse its data for delivery back to the request.request.addMarker("cache-hit");Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));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.final Request<?> finalRequest = request;mDelivery.postResponse(request, response, new Runnable() {@Overridepublic void run() {try {mNetworkQueue.put(finalRequest);} catch (InterruptedException e) {// Not much we can do about this.}}});}} catch (Exception e) {VolleyLog.e(e, "Unhandled exception %s", e.toString());}}
}
3.网络调度线程NetworkDispatcher,当缓存不存在或者过期会把请求加入到请求队列,开始工作了。
@Overridepublic void run() {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);Request<?> request;while (true) {long startTimeMs = SystemClock.elapsedRealtime();// release previous request object to avoid leaking request object when mQueue is drained.request = null;try {// Take a request from the queue.request = mQueue.take();} ...try {...// Perform the network request.//调用BasicNetwork实现类进行网络请求,并获得响应 1NetworkResponse networkResponse = mNetwork.performRequest(request);...// Parse the response here on the worker thread.//对响应进行解析Response<?> response = request.parseNetworkResponse(networkResponse);request.addMarker("network-parse-complete");...request.markDelivered();mDelivery.postResponse(request, response);// Write to cache if applicable.//将响应结果写进缓存if (request.shouldCache() && response.cacheEntry != null) {    mCache.put(request.getCacheKey(), response.cacheEntry);   request.addMarker("network-cache-written");}} ...}}4.BasicNetwork的performRequest方法:
@Overridepublic NetworkResponse performRequest(Request<?> request) throws VolleyError {long requestStart = SystemClock.elapsedRealtime();while (true) {HttpResponse httpResponse = null;byte[] responseContents = null;Map<String, String> responseHeaders = Collections.emptyMap();try {// Gather headers.Map<String, String> headers = new HashMap<String, String>();addCacheHeaders(headers, request.getCacheEntry());httpResponse = mHttpStack.performRequest(request, headers);  // 1StatusLine statusLine = httpResponse.getStatusLine();int statusCode = statusLine.getStatusCode();responseHeaders = convertHeaders(httpResponse.getAllHeaders());// Handle cache validation.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);  // 2}// A HTTP 304 response does not have all header fields. We// have to use the header fields from the cache entry plus// the new ones from the response.// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5entry.responseHeaders.putAll(responseHeaders);return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,entry.responseHeaders, true,SystemClock.elapsedRealtime() - requestStart);}       ...}}
mHttpStack.performRequest();这里调用了mHttpStack的performRequest方法,那么mHttpStack是什么呢?我们可以翻上去看看part1处实例化BasicNetwork的时候传递的stack值,该值就是根据不同的系统版本号而实例化的HttpStack对象(版本号大于9的是HurlStack,小于9的是HttpClientStack),由此可知,这里实际调用的是HurlStack.performRequest()方法,方法的内部基本是关于HttpUrlConnection的逻辑代码,这里就不展开说了。可以这么说:HurlStack封装好了HttpUrlConnection,而HttpClientStack封装了HttpClient。该方法返回了httpResponse,接着把这个响应交由处处理,封装成NetworkResponse对象并返回。在NetworkDispatcher的run()方法获取返回的NetworkResponse对象后,对响应解析.
5.ExecutorDelivery通知主线程,请看postResponse方法:
@Overridepublic void postResponse(Request<?> request, Response<?> response) {postResponse(request, response, null);}@Overridepublic void postResponse(Request<?> request, Response<?> response, Runnable runnable) {request.markDelivered();request.addMarker("post-response");mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));}在方法内部调用了mResponsePoster的execute()方法,那么,这个mResponsePoster是在哪里来的呢?其实这个成员变量是在ExecutorDelivery实例化的时候同时实例化的,而ExecutorDelivery则是在RequestQueue实例化的时候同时实例化的,读者可以自行查看相应的构造方法,其实这些工作在par 1建立请求队列的时候已经全部做好了。
接着我们可以看以下代码,ExecutorDelivery的ExecutorDelivery方法:public ExecutorDelivery(final Handler handler) {// Make an Executor that just wraps the handler.//实例化Executor,并且重写execute方法mResponsePoster = new Executor() {@Overridepublic void execute(Runnable command) {//这里获取的handler是主线程的handler,可看part 1 (2)handler.post(command);}};}
execute()方法接收一个Runnable对象,那么我们回到上面的mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));可以看出这里实例化了一个ResponseDeliveryRunnable对象作为Runnable对象。而这里的ResponseDeliveryRunnable则是当前类Executor的一个内部类,实现了Runnable接口,我们来看看:@SuppressWarnings("rawtypes")private class ResponseDeliveryRunnable implements Runnable {private final Request mRequest;private final Response mResponse;private final Runnable mRunnable;//构造方法...@Overridepublic void run() {// If this request has canceled, finish it and don't deliver.if (mRequest.isCanceled()) {mRequest.finish("canceled-at-delivery");return;}// Deliver a normal response or error, depending.if (mResponse.isSuccess()) {mRequest.deliverResponse(mResponse.result);  // 1} else {mRequest.deliverError(mResponse.error);}...}}}在上面,①号代码回调到了Request的deliverResponse方法,即此时通知了主线程,请求已经完成,此时在Request子类重写的deliverResponse方法则会调用onResponse()方法,那么我们的Activity就能方便调用解析好的请求结果了。

Volley简单分析相关推荐

  1. R语言splines包构建基于logistic回归的自然样条分析:南非心脏病数据集、非线性:基函数展开和样条分析、你简单分析的不重要特征,可能只是线性不显著、而非线性是显著的

    R语言splines包构建基于logistic回归的自然样条分析:南非心脏病数据集.非线性:基函数展开和样条分析.你简单分析的不重要特征,可能只是线性不显著.而非线性是显著的 目录

  2. [EntLib]微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇...

    在完成了后,今天开始介绍企业库中的新模块:Cryptographer(加密模块),这个模块在日常的大多数项目的作用非常重要,例如:网站会员密码.身份证号.网站配置等,通过对信息进行加密可以保证项目数据 ...

  3. FFmpeg资料来源简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg库函数的源代码的分析文章: [骨架] FFmpeg源码结构图 - 解码 FFmp ...

  4. howdoi 简单分析

    对howdoi的一个简单分析. 曾经看到过下面的这样一段js代码: try{doSth(); } catch (e){ask_url = "https://stackoverflow.com ...

  5. Mac与Phy组成原理的简单分析

    Mac与Phy组成原理的简单分析 2011-12-28 15:30:43 //http://blog.chinaunix.net/uid-20528014-id-3050217.html 本文乃fir ...

  6. python做数据可视化的代码_Python数据可视化正态分布简单分析及实现代码

    Python说来简单也简单,但是也不简单,尤其是再跟高数结合起来的时候... 正态分布(Normaldistribution),也称"常态分布",又名高斯分布(Gaussiandi ...

  7. ASIHTTPRequest源码简单分析

    2019独角兽企业重金招聘Python工程师标准>>> 1.前言 ASIHttprequest 是基于CFNetwork的,由于CFNetwork是比较底层的http库,功能比较少, ...

  8. Hessian 源码简单分析

    Hessian 源码简单分析 Hessian 是一个rpc框架, 我们需要先写一个服务端, 然后在客户端远程的调用它即可. 服务端: 服务端通常和spring 做集成. 首先写一个接口: public ...

  9. python预测股票价格tushare_用tushare对股票进行简单分析

    用tushare对股票进行简单分析(仅供交流学习) import numpy as np import pandas as pd import matplotlib.pyplot as plt imp ...

最新文章

  1. NAT环境无法访问云端的深层次分析
  2. 反射中getMethods 与 getDeclaredMethods 的区别
  3. 引用 vsftpd配置手册(实用)
  4. C++学习笔记-----在重载的赋值运算函数中调用拷贝构造函数
  5. SEO行业的路上没有捷径
  6. Cobbler安装指南
  7. 深入浅出DDoS***
  8. 【刷题】BZOJ 5154 [Tjoi2014]匹配
  9. 软件工程:NFR与NFP
  10. 给ImageView做圆角处理
  11. Get IT技能百科库 50个领域轻松直达
  12. 360浏览器出现https证书错误怎么办
  13. 红尘一醉,愿得一人心;烟火夫妻,白首不相离
  14. 使用联通云OSS小程序直传
  15. Notes Twenty-fourth days-渗透攻击-红队-红队自研
  16. Delphi2010开发DataSnap服务器(一)
  17. 3D游戏建模软件大总结,你都知道哪些?
  18. 实例:【基于机器学习的NBA球员信息数据分析与可视化】
  19. Keil软件常见配置
  20. 【MATLAB深度学习】采用Faster R-CNN实现车辆目标检测

热门文章

  1. Python你中无我
  2. 嵌入式 iptables防火墙实际使用案例解析
  3. 【计算机网络】【自顶向下课后习题-2】
  4. DOI EXCEL显示报表
  5. Shell自动化脚本学习
  6. C# word中插入页脚而不要页眉横线
  7. 一场CF的台前幕后(上)——转
  8. 平翘舌绕口令(整理)
  9. 软件工程第三次作业1
  10. Keyshot 科研作图2(材质与环境)