Volley解析(一)--Volley的使用

Volley 是一个HTTP协议的网络请求框架

Volley的优势:

  1. 自动安排网络请求
  2. 支持多个并发网络连接
  3. 具有标准HTTP缓存一致性的透明磁盘和内存响应缓存
  4. 支持请求优先级
  5. 支持取消请求api。可以取消单个请求,也可以设置要取消的请求的块或范围。
  6. 定制方便,支持失败重试和回退
  7. 强排序,可以轻松地从网络异步获取的数据中正确填充UI。
  8. 具有调试和跟踪工具

它易于与任何协议集成,支持原始字符串、图像和JSON的解析。通过提供你需要的功能的内置支持,Volley使你从写样板代码脱身,可以让你专注于特定于应用程序的逻辑。

Volley的优势劣势都在于使用内存缓存!!

Volley擅长的场景:

Volley擅长用于填充UI的RPC类型操作,如将搜索结果页作为结构化数据抓取。适合短小,频繁的请求。因为解析过程结果会保留在内存。

Volley不擅长的场景:

Volley不适合大型下载或流媒体操作,因为在解析过程中保留了内存中的所有响应。

使用newRequestQueue简单发送请求

三步完成发送请求:

  1. 初始化请求队列
  2. 构造请求对象
  3. 请求对象加入请求队列

Volley提供了一个方便的方法volley.newrequestqueue为用户配置一个请求队列.设置使用默认值,并启动队列。

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));
//UI线程
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
//UI线程
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);

Volley总是在主线上传递解析的响应。在主线程中运行可以方便与接收的数据填充的UI控件,你可以直接从响应随意修改UI控件。但是它对库提供的许多重要语义尤其重要,特别是与取消请求相关的。

一旦添加请求,它就通过管道移动,得到服务,并对其原始响应进行解析。

当调用add,Volley就会跑一个cache线程和一个网络分发线程池(默认是4个线程的线程池)。

当你添加一个请求队列,它会进缓存的线程:

如果请求可以从高速缓存中得到服务,缓存响应将在高速缓存线程上解析,解析后的响应将在主线程上传递。

如果请求不能从缓存中进行服务,那么它就被放置在网络队列中。第一个可用的网络线程接收来自队列的请求,执行HTTP事务,解析工作线程上的响应,将响应写入高速缓存,并将解析后的响应返回到主线程进行传输。

注意,诸如阻塞I/O和解析/解码等昂贵的操作是在工作线程上完成的。可以从任何线程添加请求,但响应总是在主线程上传递。

取消一个请求

这种场景是比较常见的。比如在界面销毁之前,请求就需要取消。

1 最简单的一个方式就是在请求的对象上直接调cancel()方法:

stringRequest.cancel();

一旦取消,Volley保证的响应Response处理程序将永远不会被调用。这意味着你可以取消你所有的请求在onstop()方法。而且在响应处理方法里不用检查getActivity() == null,也不用关心onSaveInstanceState()有没有被调用,或者去有意其他的一些防御性代码。

这样带来的好处是巨大的,意味着Rrsponse中的任何操作在cancel以后不会执行,那就不会有意外发生。

要利用这种行为,通常需要跟踪所有正在执行的请求,以便在适当的时候取消它们。

有一个更简单的方法:可以将标记对象与每个请求关联起来。然后可以使用此标记来提供取消请求的范围。

可以将所有请求标记为正在进行的界面。然后再onStop中调requestQueue.cancelAll(this)。同样,你也可以用tag标记把所有的缩略图图片请求和ViewPager中各个相关的tab页关联起来。在切换的时候就取消前一个tab的请求们

2 批量范围取消请求

//先标记

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); //再在onStop方法中取消
@Override
protected void onStop () {
super.onStop();
if (mRequestQueue != null) {
mRequestQueue.cancelAll(TAG);
}
}

注意:要谨慎嗲用cancel方法.假设这样一个场景:你要根据请求的返回结果做下一步工作。而这步的工作在成功或者失败的时候都要执行。那如果取消掉了请求。这段必须执行的逻辑就永远执行不到了。

再次说明:cancel后 ,response处理程序将不会被调用

脱离newRequestQueue自己配置一个请求队列

Volley.newRequestQueue 简化了请求队列的构造。但如果要自定义请求队列就要自己配置。一个网络请求队列需要两个工具:网络执行请求的运输,和缓存处理缓存。

Volley toolbox有标准的实现。diskbasedcache采用文件/响应缓存一一对应的方式提供一个内存索引。

BasicNetwork提供了一个基于首选的HTTP客户端的网络传输。默认是HttpUrlConnection API9一下是HttpClient

RequestQueue mRequestQueue;

// Instantiate the cache
Cache 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 queue
mRequestQueue.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); // ...

如果支持做一次性的请求操作那用Volley.newRequestQueue就行了。然后再相应返回或者错误以后调用RequestQueue的stop把请求的线程池停掉就行了。

但是通常情况的场景是在app的整个运行期内都要维持这个队列,把RequestQueue作为一个单例用。

单例模式的RequestQueue

最直接的方式就是在Application的onCreate中构建RequestQueue对象。但是这样做并不是最好的。

最好的方式就是用静态单例更模块化的方式提供相同的功能

一个关键的概念是,所以必须实例化时使用ApplicationContext,不是一个ActivityContext。这样是为了保证RequestQueue的生命周期和app存货的时间是一样的。

	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 RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
getRequestQueue(); // ... // Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);

实现自定义的请求对象

大多数请求已经准备好在工具箱中使用实现;如果响应是字符串、图像或JSON,则可能不需要实现自定义请求。

对于需要实现自定义请求的情况,这是需要做的全部工作:

  1. 继承Request类, 表示请求之后解析响应的类型。如果解析后的响应是String,那T就应该是String.
  2. 实现 parseNetworkResponse() 和deliverResponse()方法。

parseNetworkResponse

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));
}
// handle errors
...
}

NetworkResponse参数包含了返回的所有数据。包括byte[]形式的返回响应,HTTP状态码,响应头。

注意: 实现必须返回一个Response,并包含指定类型T的相应对象、缓存数据或者一个错误信息,比如解析失败等。

如果请求协议不是标准的缓存语法,可以自己构筑一个Cache.Entry

return Response.success(myDecodedObject,HttpHeaderParser.parseCacheHeaders(response));

Volley在工作线程调用parseNetworkResponse()方法。确保了昂贵的解析操作,例如将jpeg解码成位图,不会阻止UI线程。

deliverResponse

Volley从主线程中回调parseNetworkResponse()方法返回的对象。请求用回调接口回调回来这个对象:

protected void deliverResponse(T response) { listener.onResponse(response);

一个完整的自定义请求例子 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));
}
}
}

Volley解析(一)--Volley的使用的更多相关文章

  1. Android网络框架-Volley实践 使用Volley打造自己定义ListView

    这篇文章翻译自Ravi Tamada博客中的Android Custom ListView with Image and Text using Volley 终于效果 这个ListView呈现了一些影 ...

  2. Volley解析之表单提交篇

    要实现表单的提交,就要知道表单提交的数据格式是怎么样,这里我从某知名网站抓了一条数据,先来分析别人提交表单的数据格式.  数据包: Connection: keep-alive Content-Len ...

  3. DownloadProvider源码解析——与Volley对比

    1.AndroidHttpClient的创建 DownloadManager: 在DownloadThread的run方法里 public void run() { Process.setThread ...

  4. Android -- Volley解析

    Volley设计 Dispatch Thread不断从RequestQueue中取出请求,根据是否已缓存调用Cache或Network这两类数据获取接口之一,从内存缓存或是服务器取得请求的数据,然后交 ...

  5. Volley 解析

    Volley Request处理流程 RequestQueue类中有三个基本的队列.调用RequestQueue.add(request)增加的请求会先增加mCacheQueue(优先级堵塞队列)由C ...

  6. 源码解析-Volley(转自codeKK)

    Volley 源码解析 本文为 Android 开源项目源码解析 中 Volley 部分项目地址:Volley,分析的版本:35ce778,Demo 地址:Volley Demo分析者:grumoon ...

  7. [转] Android Volley完全解析(一),初识Volley的基本用法

    版权声明:本文出自郭霖的博客,转载必须注明出处.   目录(?)[-] Volley简介 下载Volley StringRequest的用法 JsonRequest的用法   转载请注明出处:http ...

  8. Android Volley完全解析

    1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...

  9. volley源代码解析(七)--终于目的之Response&lt;T&gt;

    在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...

随机推荐

  1. java.lang.NoClassDefFoundError: org/apache/commons/collections/map/LRUMap 解决方法

    转自:https://blog.csdn.net/q664243624/article/details/69221324

  2. ipv4 ipv6简介

    互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),缩写为IP地址(IP Address),在Internet上,一种给主机编址的方式.常见的IP地址,分为 ...

  3. 编译portmap和nfs-utils

    编译portmap和nfs-utils 为了在播放机上实现NFS服务器的功能,我们已经在uClibc中打开了完整RPC支持,并且在新编译的内核中打开了NFS服务器支持.此外还有两个软件包也是提供NFS ...

  4. UniqueIdentifier 数据类型

    UniqueIdentifier 数据类型用于存储GUID的值,占用16Byte. SQL Server将UniqueIdentifier存储为16字节的二进制数值,Binary(16),按照特定的格 ...

  5. sql中的高级编程(函数,存储过程,视图)

    一.函数:用sql写一个函数,调用这个函数,返回一张数据表table CREATE FUNCTION FunName ( ) RETURNS @TempTable table ( roleid int ...

  6. 痞子衡嵌入式:微处理器CPU性能测试基准(Dhrystone)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是微处理器CPU性能测试基准Dhrystone. 在嵌入式系统行业用于评价CPU性能指标的标准主要有三种:Dhrystone.MIPS.C ...

  7. Git 时光穿梭鸡 管理修改

    Git跟踪并管理的是修改,而非文件. 什么是修改? 比如你新增了一行,这就是一个修改, 删除了一行,也是一个修改, 更改了某些字符,也是一个修改, 删了一些又加了一些,也是一个修改, 甚至创建一个新文 ...

  8. SVN版本控制图标未显示或显示异常解决方法

    SVN版本控制图标未显示问题解决方法,刚开始遇到这个问题的时候,好苦恼.经过“千辛万苦”的努力,终于得以解决,分享给大家,希望能帮到各位哦! 工具/原料   SVN安装包 方法/步骤     首先安装 ...

  9. 洛谷P3200 [HNOI2009]有趣的数列(Catalan数)

    P3200 [HNOI2009]有趣的数列 题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足 ...

  10. 字符环(openjudge 2755)

    字符环 总时间限制: 1000ms   内存限制: 65536kB 描述 有两个由字符构成的环.请写一个程序,计算这两个字符环上最长连续公共字符串的长度.例如,字符串“ABCEFAGADEGKABUV ...