《Volley源码分析》Part1、Volley的使用以及介绍
来源:互联网 发布:张逗张花 知乎 编辑:程序博客网 时间:2024/05/21 19:43
1、简单介绍
因为说了是简单介绍,这里就不做复杂说明。
Volley是google方法出品的网络框架,在Goolge IO 2013大会上发布,目前在Android develop Training可以看到介绍,Training介绍原文地址,这个地址是需要翻墙的。
在附上介绍视频地址,同样也是需要翻墙的。Volley: Easy, Fast Networking for Android。
虽然现在大家项目中可能都使用的是 Retrofit,但是学习一下Volley还是很有必要的,总的来说是Android的google爸爸出品的,而且就目前状态来看,代码仍然在维护中。
2、Transmitting Network Data Using Volley(使用Volley进行网络数据传输)
Volley是一个HTTP库,它使Android应用程序的网络更容易,最重要的是更快。
Volley可以在Github上找到代码
Volley具有以下特点:
- 1、自动调度网络请求
- 2、支持多个并发网络连接
- 3、具有标准的HTTP缓存一致性的硬盘和内存缓存
- 4、支持请求优先级
- 5、支持请求取消API,可以取消单个请求,也支持设置要取消的请求的块或范围
- 6、更加容易自行定制
- 7、强健的顺序性可以保证异步获取的数据正确的填充你的UI
- 8、Debugging and tracing tools.
Volley擅长用于填充UI的RPC-TYPE操作,如将搜索结果页作为结构化数据抓取。它易于与任何协议集成,并为输出原始字符串、images和JSON提供了内建的支持。可以让你更加专注于具体的业务逻辑功能。
Volley不适合大型下载或者流媒体操作,因为为了方便解析Volley在内存中持有了所有的Response信息。对于大型下载可以考虑使用其他方式,比如DownloadManager。
如果想在你的项目中集成Volley,可以加入如下的代码
dependencies { ... compile 'com.android.volley:volley:1.0.0'}
当然你也可以clone下来代码,以module的形式加入到项目中
git clone https://github.com/google/volley
2、Sending a Simple Request(发送一个简单的请求)
2-1、添加INTERNET权限
<uses-permission android:name="android.permission.INTERNET" />
2-2、使用RequestQueue
Volley提供了一个方便的方法Volley.newRequestQueue去配置RequestQueue,当然是用的默认值去开启队列。下面是使用例子。
final TextView mTextView = (TextView) findViewById(R.id.text);...// Instantiate the RequestQueue.RequestQueue queue = Volley.newRequestQueue(this);String url ="http://www.google.com";// Request a string response from the provided URL.StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Display the first 500 characters of the response string. mTextView.setText("Response is: "+ response.substring(0,500)); }}, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mTextView.setText("That didn't work!"); }});// Add the request to the RequestQueue.queue.add(stringRequest);
Volley总是将解析的返回结果呈现在主线程中,这样方便了去做UI相关的填充处理操作,你可以方便的拿到数据去直接修改ui控件。它还提供了很多有用的功能,比如取消一个请求。
2-3、发送请求
发送一个请求,你只需要构造一个请求,并把它通过RequestQueue#add()
方法添加到RequestQueue
中去,在添加了请求之后,它将通过管道(pipeline)移动,得到服务,并对其原始相应进行解析和分发。
当你调用add()
方法,Volley将运行一个缓存处理线程和一个网络调度线程池。当你添加一个请求到队列中,它将被缓存线程进行一个判断,如果请求对应的缓存服务可以工作,也就是说请求的缓存存在并且没有过期,缓存线程会进行解析并且分发返回结果到主线程(UI线程)。如果不能从缓存中获取(这里也包括缓存过期的情况),那么它就被放置在消息队列中。有一个网络任务线程去处理请求,执行HTTP事务,解析工作线程上的返回结果,将返回结果写入缓存,并将解析后的结果返回分发到主线程中。
note:诸如阻塞IO,解析数据等这种耗时操作都是在工作线程中完成的,你可以从任何线程添加一个请求,但是响应总是要在主线程。
2-4、取消请求
取消一个请求,在你的Request对象调用cancel()。一旦取消,Volley保证你的响应结果处理分发将永远不同被调用(个人理解是不管你网络请求处理结果如何,一旦取消,负责结果分发的处理就中断了)。这就意味着你可以在onStop
中取消你的没有执行的请求,而且你完全不用去在你的请求结果处理返回部分检查getActivity() == null
(反正这块处理逻辑都不会走了)。
要使用这种行为,你应该追踪你所有的飞行请求(in-flight: 应该理解为所有的已经请求,但是还没有拿到请求结果的请求),以便在合适的时机取消它们。这里有一个简单方法:你可以用一个标记(tag)和请求关联起来,然后你可以用这个标记来提供取消的范围。
Here is an example that uses a string value for the tag:
- 1、Define your tag and add it to your requests.
public static final String TAG = "MyTag";StringRequest stringRequest; // Assume this exists.RequestQueue mRequestQueue; // Assume this exists.// Set the tag on the request.stringRequest.setTag(TAG);// Add the request to the RequestQueue.mRequestQueue.add(stringRequest);
- 2、In your activity’s onStop() method, cancel all requests that have this tag.
@Overrideprotected void onStop () { super.onStop(); if (mRequestQueue != null) { mRequestQueue.cancelAll(TAG); }}
取消请求时要注意,如果你的请求结果需要推进一个状态或者另一个进程,你应该了解到,这个对应的处理(状态或者另一个进程相关操作)同样不会被调用到。
3、Setting Up a RequestQueue(配置RequestQueue)
3-1、设置网络和缓存
一个RequestQueue会做两个工作:传输网络请求和处理数据缓存。在Volley的自带工具箱(toolbox)中提供了默认实现:
DiskBaseCache
提供一个与内存中索引一一对应的文件。BasicNetwork
提供一个基于HTTP的网络传输协议客户端。
BasicNetwork
是Volley的默认网络实现,一个网络必须与您的应用程序使用HTTP客户端初始化链接网络,通常是HttpUrlConnection
。
下面代码片段展示如何设置RequestQueue
RequestQueue mRequestQueue;// Instantiate the cacheCache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap// Set up the network to use HttpURLConnection as the HTTP client.Network network = new BasicNetwork(new HurlStack());// Instantiate the RequestQueue with the cache and network.mRequestQueue = new RequestQueue(cache, network);// Start the queuemRequestQueue.start();String url ="http://www.example.com";// Formulate the request and handle the response.StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Do something with the response }}, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // Handle error }});// Add the request to the RequestQueue.mRequestQueue.add(stringRequest);// ...
如果你只想要做一次请求,不需要线程池,你可以创建一个RequestQueue在你任何需要的地方,在数据返回之后,调用stop()即可。更常用的方法是直接使用Volley.newRequestQueue()去执行一个简单的请求,并且保持RequestQueue在你的应用程序中单例存在。
3-2、使用单例模式
为了使整个应用的生命周期中,你的网络请求都可用,可以将RequestQueue设置为单例模式。
一个需要注意的点是,RequestQueue必须使用Application Context进行初始化,而不是Activity Context,这将确保了RequestQueue在整个应用的生命周期有效。
public class MySingleton { private static MySingleton mInstance; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; private static Context mCtx; private MySingleton(Context context) { mCtx = context; mRequestQueue = getRequestQueue(); mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() { private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20); @Override public Bitmap getBitmap(String url) { return cache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { cache.put(url, bitmap); } }); } public static synchronized MySingleton getInstance(Context context) { if (mInstance == null) { mInstance = new MySingleton(context); } return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); } return mRequestQueue; } public <T> void addToRequestQueue(Request<T> req) { getRequestQueue().add(req); } public ImageLoader getImageLoader() { return mImageLoader; }}
下面是一个使用实例:
// Get a RequestQueueRequestQueue queue = MySingleton.getInstance(this.getApplicationContext()). getRequestQueue();// ...// Add a request (in this example, called stringRequest) to your RequestQueue.MySingleton.getInstance(this).addToRequestQueue(stringRequest);
4、Making a Standard Request(发起一个标准请求)
Volley内建支持了如下请求类型:
StringRequest: 指定一个url,请求返回字符串类型的结果。
JsonObjectRequest和JsonArrayRequest,指定一个url,返回结果是JSON格式或者JSONAarray格式。
下面的例子,使用JsonObjectRequest展示:
TextView mTxtDisplay;ImageView mImageView;mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);String url = "http://my-json-feed";JsonObjectRequest jsObjRequest = new JsonObjectRequest (Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { mTxtDisplay.setText("Response: " + response.toString()); }}, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub }});// Access the RequestQueue through your singleton class.MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
5、Implementing a Custom Request(自定义实现一个请求)
Volley的工具箱中提供了网络请求,缓存的默认实现,以及几种请求方式,如果这些都不满足你的实际使用的话,Volley也支持自定义实现。
5-1、自定义网络请求
想要自己实现网络请求,需要如下几步:
- 1、继承
Request<T>
,这里的泛型T就是处理之后的返回结果类型,如果你期待的解析之后类型是String,可能你需要写成Request,具体的实现可以在Volley Toolbox中找到。 - 2、实现抽象方法
parseNetworkResponse()
和deliverResponse
。
parseNetworkResponse
这个方法主要是对于返回的结果集进行解析处理。
@Overrideprotected Response<T> parseNetworkResponse( NetworkResponse response) { try { String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); } // handle errors...}
parseNetworkResponse的参数NetworkResponse里面包含了HTTP状态码,header信息等内容。
deliverResponse
protected void deliverResponse(T response) { listener.onResponse(response);
5-2、Example: GsonRequest
public class GsonRequest<T> extends Request<T> { private final Gson gson = new Gson(); private final Class<T> clazz; private final Map<String, String> headers; private final Listener<T> listener; /** * Make a GET request and return a parsed object from JSON. * * @param url URL of the request to make * @param clazz Relevant class object, for Gson's reflection * @param headers Map of request headers */ public GsonRequest(String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener) { super(Method.GET, url, errorListener); this.clazz = clazz; this.headers = headers; this.listener = listener; } @Override public Map<String, String> getHeaders() throws AuthFailureError { return headers != null ? headers : super.getHeaders(); } @Override protected void deliverResponse(T response) { listener.onResponse(response); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String json = new String( response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success( gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } }}
6、实例代码
https://github.com/fireking0415/VolleySample
- 《Volley源码分析》Part1、Volley的使用以及介绍
- Volley的使用以及源码分析(一)
- Volley的使用以及源码分析(二)
- Volley的使用以及源码分析(一)
- Volley的使用以及源码分析(二)
- Volley的源码分析
- Volley的使用以及源码解析
- Volley的使用和源码分析
- android Volley的源码分析
- 对Volley的源码分析
- Android Volley源码分析(一) 简要介绍
- Volley框架的介绍使用
- Volley框架的介绍使用
- Volley框架的使用介绍
- 【进阶android】Volley源码分析——Volley的流程
- 【进阶android】Volley源码分析——Volley的线程
- 【进阶android】Volley源码分析——Volley的缓存
- 对Volley的使用分析
- 背包问题
- uva 1374 Power Calculus
- TensorFlow架构系统理解
- HDU 2054
- Single Number
- 《Volley源码分析》Part1、Volley的使用以及介绍
- .NET获取聚合数据接口数据(Http协议POST和GET请求)
- ssh免密登录实现办法及原理
- Hibernate文件详解配置
- N
- 计算机网络笔记整理(六):应用层
- FTPrep, 72 Edit Distance
- 解决android离线文档慢
- Win10 + Ubuntu双系统U盘安装,详细过程(带图解)