Volley源码解析(一),基本概述
来源:互联网 发布:赛事专用软件源码php 编辑:程序博客网 时间:2024/05/21 06:57
最近在学习Volley源码及android网络框架的构建,由此写下这篇博客作为学习的第一步总结,待将Volley源码解析完后,如果有时间也会写关于搭建android网络框架的文章,更希望能帮助到大家在这一块的学习,由 于本人的能力与时间有限,有什么不足之处还请各位指正,谢谢!!! 本文的结构分为三个部分,第一部分为Volley的总体框架的关系;第二部分是我们使用Volley框架时的运行原理;第三部分为Volley中一些核心的类的作用。下面开启我们的Volley学习之旅吧。
一、总体架构的关系:
本图片中的其中蓝色部分代表主线程,也就是activity运行的UI线程,绿色部分代表缓存线程Cache类,橙色部分代表网络线程主要是Network类。Volley默认的是一个缓存线程与4个网络线程,我们在主线程中调用RequestQueue的add()方法来添加一条网络请求,这条请求会先被加入到缓存队列当中,HTTP请求,解析响应结果,写入缓存,并回调主线程。
二、Volley的使用原理:
以StringRequest为例,且sdk大于9,当我们在使用volley时,一般会这样写:
//获取到一个RequestQueue请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue mQueue = Volley.newRequestQueue(context);//创建一个StringRequest对象,此请求为Get请求StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.d("TAG", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); //将这个StringRequest对象添加到RequestQueue里面就可以了mQueue.add(stringRequest);
当程序调用上面第一行代码时的运行逻辑图:
第一行的这么一句代码是至关重要的,为后面的网络请求做好了准备。第一步创建cacheDir目录用于网络请求的缓存。第二步创建Network,用于执行StringRequest请求,其中有一个重要方法performRequest()将参数request提取关键数据,调用mHttpStack.performRequest()发起网络访问,分解反馈httpResponse的statusCode封装不同的NetworkResponse。第三步创建RequestQueue消息队列,消息队列维护了提交给网络框架的请求列表,并且根据相应的规则进行排序。默认情况下根据优先级和进入队列的顺序来执行,该队列使用的是线程安全的PriorityBlockingQueue,因为我们的队列会被并发的访问,因此需要保证访问的原子性。的请求队列,请求完成之后将结果投递给UI线程。
源代码如下:
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;}
结合上面的图,源代码还是很好理解的,在此就不重复了。
当程序调用第二行时的运行逻辑图:
此时只是进行一些参数的设置,以及接口返回数据的处理。
源代码如下:
public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener;//数据请求信息回应的一个监听}
super的源码如下:
public Request(int method, String url, Response.ErrorListener listener) { mMethod = method; mUrl = url; mErrorListener = listener; setRetryPolicy(new DefaultRetryPolicy()); //设置优先级 mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); //设置活动标签}<br/>
当调用最后一行时的运行逻辑图:
通过这句代码,对新add的request,设置归属队列,放入mCurrentRequest表示正大处理,并设置一下加入队列的顺序,设置是否需要对
request进行cache。此时网络请求已经准备就绪了,等待NetworkDispatcher的处理。
源代码如下:
public Request add(Request request) { // Tag the request as belonging to this queue and add it to the set of current requests. 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. 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.put(cacheKey, null); mCacheQueue.add(request); } return request; }}
三、Volley中的一些类的概念
Volley:通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue。
Request:表示一个请求的抽象类。StringRequest、JsonRequest、ImageRequest ,MultipartRequest都是它的子类,表示某种类型的请求。
RequestQueue:表示请求队列,里面包含一个CacheDispatcher(用于处理缓存请求的调度线程)、NetworkDispatcher数组(用于处理网络请求的调度线程),一个ResponseDelivery(返回结果分发接口),通过 start() 函数启动时会启动CacheDispatcher和NetworkDispatchers。
CacheDispatcher:一个线程,用于调度处理走缓存的请求。启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理。当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher去调度处理。
NetworkDispatcher:一个线程,用于调度处理走网络的请求。启动后会不断从网络请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery去执行后续处理,并判断结果是否要进行缓存。
ResponseDelivery:返回结果分发接口,目前只有基于ExecutorDelivery的在入参 handler 对应线程内进行分发。
HttpStack:处理 Http 请求,返回请求结果。目前 Volley 中有基于 HttpURLConnection 的HurlStack和 基于 Apache HttpClient 的HttpClientStack。
Network:调用HttpStack处理请求,并将结果转换为可被ResponseDelivery处理的NetworkResponse。
Cache:缓存请求结果,Volley 默认使用的是基于 sdcard 的DiskBasedCache。NetworkDispatcher得到请求结果后判断是否需要存储在 Cache,CacheDispatcher会从 Cache 中取缓存结果。
其他还有许多细节完善的类,在此就不多提了,每个类都有其固定的功能,而且分工明确,核心的几个类基本列出。
今天的总结就先到这里了。下期再见!!!
- Volley源码解析(一),基本概述
- Volley 源码解析(一)
- Volley源码解析(一)
- Volley源码解析(一)
- Volley源码解析(一)
- Volley源码解析(一)
- Android Volley完全解析(一),Volley的基本用法
- Android Volley详细解析(一):Volley基本用法
- 3、Volley解析(一),了解Volley的基本用法
- Volley学习(一)Android Volley源码解析
- [Android]Volley源码分析(一)概述
- Volley基本使用及源码解析
- ZooKeeper源码解析(一):ZooKeeper概述
- Picasso源码完全解析(一)--概述
- Volley源码解析(一):网络请求内容
- Volley框架使用与源码解析(一)
- Volley源码解析 --- Volley组成(1)
- 【Volley】Volley源码解析
- hdu 1039 Easier Done Than Said?
- 1.系统调用的过程
- Light OJ 1031 Easy Game 区间DP
- Summer Training Team Selection (1) Problem F Line Them Up 判断升序降序
- 学习PS基础
- Volley源码解析(一),基本概述
- 算法导论学习笔记(二)分治策略之最大子数组
- javascript中Object.create与new的不同
- OpenCV学习之安装
- 343. Integer Break
- 2.一个奇怪的fork程序
- iOS中实现获取文本内容的宽高
- 实习面试经验
- 3.fork()到底干了啥?