原文链接:http://blog.csdn.net/guolin_blog/article/details/17482165,CSDN 郭霖

1. Volley简介

我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据。Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,几乎在任何项目的代码中我们都能看到这两个类的身影,使用率非常高。

不过HttpURLConnection和HttpClient的用法还是稍微有些复杂的,如果不进行适当封装的话,很容易就会写出不少重复代码。于是乎,一些Android网络通信框架也就应运而生,比如说AsyncHttpClient,它把HTTP所有的通信细节全部封装在了内部,我们只需要简单调用几行代码就可以完成通信操作了。再比如Universal-Image-Loader,它使得在界面上显示网络图片的操作变得极度简单,开发者不用关心如何从网络上获取图片,也不用关心开启线程、回收图片资源等细节,Universal-Image-Loader已经把一切都做好了。

Android开发团队也是意识到了有必要将HTTP的通信操作再进行简单化,于是在2013年Google I/O大会上推出了一个新的网络通信框架——Volley。Volley可是说是把AsyncHttpClient和Universal-Image-Loader的优点集于了一身,既可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片。除了简单易用之外,Volley在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。

下图所示的这些应用都是属于数据量不大,但网络通信频繁的,因此非常适合使用Volley。

2. 下载Volley

介绍了这么多理论的东西,下面我们就准备开始进行实战了,首先需要将Volley的jar包准备好,如果你的电脑上装有Git,可以使用如下命令下载Volley的源码:

git clone https://android.googlesource.com/platform/frameworks/volley  

下载完成后将它导入到你的Eclipse工程里,然后再导出一个jar包就可以了。如果你的电脑上没有Git,那么也可以直接使用我导出好的jar包,下载地址是:http://download.csdn.net/detail/sinyu890807/7152015

新建一个Android项目,将volley.jar文件复制到libs目录下,这样准备工作就算是做好了

3. StringRequest的用法

前面已经说过,Volley的用法非常简单,那么我们就从最基本的HTTP通信开始学习吧,即发起一条HTTP请求,然后接收HTTP响应。首先需要获取到一个RequestQueue对象,可以调用如下方法获取到:

RequestQueue mQueue = Volley.newRequestQueue(context);  

注意这里拿到的RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。

接下来为了要发出一条HTTP请求,我们还需要创建一个StringRequest对象,如下所示:

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);  }  });  

可以看到,这里new出了一个StringRequest对象,StringRequest的构造函数需要传入三个参数,第一个参数就是目标服务器的URL地址,第二个参数是服务器响应成功的回调,第三个参数是服务器响应失败的回调。其中,目标服务器地址我们填写的是百度的首页,然后在响应成功的回调里打印出服务器返回的内容,在响应失败的回调里打印出失败的详细信息。

最后,将这个StringRequest对象添加到RequestQueue里面就可以了,如下所示:

mQueue.add(stringRequest);  

另外,由于Volley是要访问网络的,因此不要忘记在你的AndroidManifest.xml中添加如下权限:

<uses-permission android:name="android.permission.INTERNET" />  

好了,就是这么简单,如果你现在运行一下程序,并发出这样一条HTTP请求,就会看到LogCat中会打印出如下图所示的数据。

没错,百度返回给我们的就是这样一长串的HTML代码,虽然我们看起来会有些吃力,但是浏览器却可以轻松地对这段HTML代码进行解析,然后将百度的首页展现出来。

这样的话,一个最基本的HTTP发送与响应的功能就完成了。你会发现根本还没写几行代码就轻易实现了这个功能,主要就是进行了以下三步操作:

  1. 创建一个RequestQueue对象
  2. 创建一个StringRequest对象
  3. 将StringRequest对象添加到RequestQueue里面

不过大家都知道,HTTP的请求类型通常有两种,GET和POST,刚才我们使用的明显是一个GET请求,那么如果想要发出一条POST请求应该怎么做呢?StringRequest中还提供了另外一种四个参数的构造函数,其中第一个参数就是指定请求类型的,我们可以使用如下方式进行指定:

StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener);  

可是这只是指定了HTTP请求方式是POST,那么我们要提交给服务器的参数又该怎么设置呢?很遗憾,StringRequest中并没有提供设置POST参数的方法,但是当发出POST请求的时候,Volley会尝试调用StringRequest的父类——Request中的getParams()方法来获取POST参数,那么解决方法自然也就有了,我们只需要在StringRequest的匿名类中重写getParams()方法,在这里设置POST参数就可以了,代码如下所示:

StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener) {  @Override  protected Map<String, String> getParams() throws AuthFailureError {  Map<String, String> map = new HashMap<String, String>();  map.put("params1", "value1");  map.put("params2", "value2");  return map;  }
};  

你可能会说,每次都这样用起来岂不是很累?连个设置POST参数的方法都没有。但是不要忘记,Volley是开源的,只要你愿意,你可以自由地在里面添加和修改任何的方法,轻松就能定制出一个属于你自己的Volley版本。

4. JsonRequest的用法

学完了最基本的StringRequest的用法,我们再来进阶学习一下JsonRequest的用法。类似于StringRequest,JsonRequest也是继承自Request类的,不过由于JsonRequest是一个抽象类,因此我们无法直接创建它的实例,那么只能从它的子类入手了。JsonRequest有两个直接的子类,JsonObjectRequest和JsonArrayRequest,从名字上你应该能就看出它们的区别了吧?一个是用于请求一段JSON数据的,一个是用于请求一段JSON数组的。

至于它们的用法也基本上没有什么特殊之处,先new出一个JsonObjectRequest对象,如下所示:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://m.weather.com.cn/data/101010100.html", null,  new Response.Listener<JSONObject>() {  @Override  public void onResponse(JSONObject response) {  Log.d("TAG", response.toString());  }  }, new Response.ErrorListener() {  @Override  public void onErrorResponse(VolleyError error) {  Log.e("TAG", error.getMessage(), error);  }  });  

可以看到,这里我们填写的URL地址是http://m.weather.com.cn/data/101010100.html,这是中国天气网提供的一个查询天气信息的接口,响应的数据就是以JSON格式返回的,然后我们在onResponse()方法中将返回的数据打印出来。

最后再将这个JsonObjectRequest对象添加到RequestQueue里就可以了,如下所示:

mQueue.add(jsonObjectRequest);  

这样当HTTP通信完成之后,服务器响应的天气信息就会回调到onResponse()方法中,并打印出来。现在运行一下程序,发出这样一条HTTP请求,就会看到LogCat中会打印出如下图所示的数据。

由此可以看出,服务器返回给我们的数据确实是JSON格式的,并且onResponse()方法中携带的参数也正是一个JSONObject对象,之后只需要从JSONObject对象取出我们想要得到的那部分数据就可以了。

你应该发现了吧,JsonObjectRequest的用法和StringRequest的用法基本上是完全一样的,Volley的易用之处也在这里体现出来了,会了一种就可以让你举一反三,因此关于JsonArrayRequest的用法相信已经不需要我再去讲解了吧。

5. 请求的生命周期

请注意那些比较耗时的操作,例如I/O与解析parsing/decoding都是执行在工作线程。你可以在任何线程中添加一个请求,但是响应结果都是返回到主线程的。

下图1,演示了一个请求的生命周期:

6. 取消请求

对请求Request对象调用cancel()方法取消一个请求。一旦取消,Volley会确保你的响应Handler不会被执行。这意味着在实际操作中你可以在activity的onStop()方法中取消所有pending在队列中的请求。你不需要通过检测getActivity() == null来丢弃你的响应handler,其他类似onSaveInstanceState()等保护性的方法里面也都不需要检测。

为了利用这种优势,你应该跟踪所有已经发送的请求,以便在需要的时候可以取消他们。有一个简便的方法:你可以为每一个请求对象都绑定一个tag对象。然后你可以使用这个tag来提供取消的范围。例如,你可以为你的所有请求都绑定到执行的Activity上,然后你可以在onStop()方法执行requestQueue.cancelAll(this) 。同样的,你可以为ViewPager中的所有请求缩略图Request对象分别打上对应Tab的tag。并在滑动时取消这些请求,用来确保新生成的tab不会被前面tab的请求任务所卡到。

下面一个使用String来打Tag的例子:

1、 定义你的tag并添加到你的请求任务中。

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、 在activity的onStop()方法里面,取消所有的包含这个tag的请求任务。

@Override
protected void onStop () {super.onStop();if (mRequestQueue != null) {mRequestQueue.cancelAll(TAG);}
}

当取消请求时请注意:如果你依赖你的响应handler来标记状态或者触发另外一个进程,你需要对此进行考虑。再说一次,response handler是不会被执行的。

多级别取消

RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
//3. 发起请求
queue.add(stringRequest);
//取消单个请求
stringRequest.cancel();//取消一个请求
//取消所有请求
queue.cancelAll(null);//取消请求队列里面所有的方法
//取消置顶tag的请求
queue.cancelAll("tag1");//取消tag为tag1的一个请求
//请求添加tag-->tag的目的就是为了反查
stringRequest.setTag("tag1");
//两个不同的请求可以设置同一个tag
stringRequest.setTag("tag1");
//  stringRequest1.setTag("tag1");

生命周期的联动

StringRequest req2 = null;
StringRequest req3 = null;
StringRequest req4 = null;
StringRequest req5 = null;req1.setTag(this.getClass().getSimpleName());
req2.setTag(this.getClass().getSimpleName());
req3.setTag(this.getClass().getSimpleName());
req4.setTag(this.getClass().getSimpleName());
req5.setTag(this.getClass().getSimpleName());// 取消对应activity里面所有的请求
RequestQueue queue = VolleyTools.getInstance(MainActivity.this).getQueue();
queue.cancelAll(this.getClass().getSimpleName());// MainActivity

7. 建立网络和缓存

一个 RequestQueue 需要两部分来支持它的工作:一部分是网络操作,用来传输请求,另外一个是用来处理缓存操作的 Cache。在 Volley 的工具箱中包含了标准的实现方式:DiskBasedCache 提供了每个文件与对应响应数据一一映射的缓存实现。 BasicNetwork 提供了一个基于 AndroidHttpClient 或者 HttpURLConnection 的网络传输。

BasicNetwork 是 Volley 默认的网络操作实现方式。一个 BasicNetwork 必须使用我们的 app 用于连接网络的 HTTP Client 进行初始化。这个 Client 通常是AndroidHttpClient 或者 HttpURLConnection:

  • 对于 app target API level 低于 API 9(Gingerbread)的使用 AndroidHttpClient。在 Gingerbread 之前,HttpURLConnection 是不可靠的。对于这个的细节,请参考 Android’s HTTP Clients。
  • 对于 API Level 9 以及以上的,使用 HttpURLConnection。

我们可以通过检查系统版本选择合适的 HTTP Client,从而创建一个能够运行在所有 Android 版本上的应用。例如:

HttpStack stack;
...
// If the device is running a version >= Gingerbread...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {// ...use HttpURLConnection for stack.
} else {// ...use AndroidHttpClient for stack.
}
Network network = new BasicNetwork(stack);

下面的代码片段演示了如何一步步建立一个 RequestQueue:

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.myurl.com";// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,new Response.Listener<String>() {@Overridepublic void onResponse(String response) {// Do something with the response}
},new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {// Handle error}
});// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
...

如果我们仅仅是想做一个单次的请求并且不想要线程池一直保留,我们可以通过使用在前面一课:发送一个简单的请求(Sending a Simple Request)文章中提到的 Volley.newRequestQueue() 方法,在任何需要的时刻创建 RequestQueue,然后在我们的响应回调里面执行 stop() 方法来停止操作。但是更通常的做法是创建一个 RequestQueue 并设置为一个单例。下面部分将演示这种做法。

8. 使用单例模式

如果我们的应用需要持续地使用网络,更加高效的方式应该是建立一个 RequestQueue 的单例,这样它能够持续保持在整个 app 的生命周期中。我们可以通过多种方式来实现这个单例。推荐的方式是实现一个单例类,里面封装了 RequestQueue 对象与其它的 Volley 功能。另外一个方法是继承 Application 类,并在 Application.OnCreate() 方法里面建立 RequestQueue。但是我们并不推荐这个方法,因为一个 static 的单例能够以一种更加模块化的方式提供同样的功能。

一个关键的概念是 RequestQueue 必须使用 Application context 来实例化,而不是 Activity context。这确保了 RequestQueue 在我们 app 的生命周期中一直存活,而不会因为 activity 的重新创建而被重新创建(例如,当用户旋转设备时)。

下面是一个单例类,提供了 RequestQueueImageLoader 功能:

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);@Overridepublic Bitmap getBitmap(String url) {return cache.get(url);}@Overridepublic 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;}
}

下面演示了利用单例类来执行 RequestQueue 的操作:

// 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);

好了,关于Volley的基本用法就讲到这里,下篇文章中我会带领大家继续探究Volley。感兴趣的朋友请继续阅读Android Volley完全解析(二),使用Volley加载网络图片

Android Volley完全解析1:初识Volley的基本用法相关推荐

  1. Android Volley完全解析(一),初识Volley的基本用法 转载地址:http://blog.csdn.net/guolin_blog/article/details/17482095

    转载地址:http://blog.csdn.net/guolin_blog/article/details/17482095 1. Volley简介 我们平时在开发Android应用的时候不可避免地都 ...

  2. Android Volley完全解析(一),初识Volley的基本用法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17482095 1. Volley简介 我们平时在开发Android应用的时候不可避 ...

  3. Android Volley完全解析3:定制自己的Request

    原文链接:http://blog.csdn.net/guolin_blog/article/details/17612763,CSDN 郭霖 经过前面两篇文章的学习,我们已经掌握了Volley各种Re ...

  4. Android Volley完全解析2:使用Volley加载网络图片

    原文链接:http://blog.csdn.net/guolin_blog/article/details/17482165,CSDN 郭霖 在上一篇文章中,我们了解了Volley到底是什么,以及它的 ...

  5. Android Volley完全解析(二),使用Volley加载网络图片 转载:http://blog.csdn.net/guolin_blog/article/details/174

    转载:http://blog.csdn.net/guolin_blog/article/details/17482165 在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中 ...

  6. Android Volley完全解析4:带你从源码的角度理解Volley

    原文链接:http://blog.csdn.net/guolin_blog/article/details/17656437,CSDN 郭霖 经过前三篇文章的学习,Volley的用法我们已经掌握的差不 ...

  7. Android Volley完全解析(四),带你从源码的角度理解Volley

    经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是对于Volley的工作原理,恐怕有很多朋友还不是很清楚.因此,本篇文章中我们就来一起阅读一下Volley的源码,将它的工作流程整体地 ...

  8. Android之解剖网络请求框架Volley

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! Volley介绍 Volley是Google推出的网络请求库,包含的特性有JSON ...

  9. Android应用中网络请求库Volley的使用

    接上文,这次来说一下如何使用Volley,会给出一些范例,和原理 Volley使用 StringRequest // 初始化一个请求队列,RequestQueue是volley库的类 RequestQ ...

最新文章

  1. 百度某员工抱怨:前人代码写得像坨*,颠覆了对大厂的认知
  2. 干货丨从概念到案例:初学者须知的十大机器学习算法
  3. Shell编程中Shift的用法
  4. C语言 文件读写 fputc 函数 - C语言零基础入门教程
  5. 切割照片php上传,php下ajax的文件切割上传
  6. c语言中 flag.bit7,利用proteus学习ARM(LPC2103)之二:熟悉IAR C语言开发环境
  7. 计算机网络校园网络设计方案,毕业论文--《计算机网络》校园网设计方案
  8. 设计模式11_装饰器
  9. 响应式网站导航html,jQuery和CSS3响应式网站导航幻灯片插件
  10. CATIA_CAA_RADER26+VS2012安装教程
  11. 找不到好看的电影就看《IMDB排名前500电影》
  12. 2020年精选网络性能监控系统
  13. Omniverse数字孪生实战
  14. 同花顺没签三方要赔钱才能拿回三方!!!!
  15. ptb同一屏呈现两张图片matlab,Psychtoolbox-3 / PTB-3 for Matlab 入门
  16. 【编程实践】Raft 算法的原理 go代码实例
  17. 正版软件 Microsoft 365 家庭版 1用户 58
  18. 第三方支付专业术语集锦
  19. pthread_cond_wait()理解
  20. 椭圆曲线:超级完整的椭圆曲线学习记录

热门文章

  1. linux 文件删除恢复
  2. C#学习笔记(一)变量 常量 基本数据类型 其它
  3. 金仓Linux安装版取消开机自启服务
  4. Redis在Linux上编译
  5. 优化数据库大幅度提高Oracle的性能
  6. Android远程桌面助手(B1391)
  7. 20个命令行工具监控 Linux 系统性能(转载)
  8. VS2010下创建WEBSERVICE,第二天 ----你会在C#的类库中添加web service引用吗?
  9. android 4.0之前版本号出现JSONException异常
  10. Google 菜市场(Android Market)上不去的解决方法