Volley是2013年谷歌官方推出的Android平台的网络通信库,Volley适用于并发和对效率、性能要求比较高的场景。
优点:
(1)使通信更快、更简单
(2)高效的get、post网络请求以及网络图像的高效率异步处理请求
(3)能对网络请求进行排序、优先级处理
(4)网络图片加载和缓存
(5)多级别取消请求,当有多个网络请求同时进行的时候,可以进行同时取消操作
(6)和Activity生命周期的联动,当Activity结束销毁时,可以同时取消网络请求操作
(7)性能稳定
缺点:
(1)不适合数据的上传下载
Github下载:
https://github.com/mcxiaoke/android-volley
Maven下载:
http://central.maven.org/maven2/com/mcxiaoke/volley/library/
在进行get、post请求之前要确定请求的数据返回的类型是哪种类型,Volley提供了三种类型:
StringRequest:返回结果类型不确定的情况使用
JsonObjectRequest:返回结果类型为JsonObject
JsonArrayRequest:返回结果类型为JsonArray
(1)首先需要为应用程序建立全局请求队列
public class MyApplication extends Application {
public static RequestQueue queue;
@Override
public void onCreate() {
super.onCreate();
// 建立Volley全局请求队列
queue = Volley.newRequestQueue(getApplicationContext()); // 实例化RequestQueue对象
}
public static RequestQueue getHttpQueue() {
return queue;
}
}
注意:需要把MyApplication注册到AndroidManifest.xml中,并加上网络请求权限。
(2)Volley的get请求
/** * 返回结果类型不确定的情况下 */
private void volleyGet(String url) {
/** * int method 请求方式 * String url 请求接口地址 * Listener<String> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
StringRequest request = new StringRequest(Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String arg0) {
System.out.println("请求成功:" + arg0); // 输出请求成功的返回结果
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
System.out.println("请求失败:" + arg0);
}
});
request.setTag("homeGet"); // 这个Tag设置的要有意义
MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}
/** * 返回结果类型为JsonObject * 注意:返回结果类型为JsonArray的请求方法和JsonObject类似 */
private void volleyJOGet(String url) {
/** * int method 请求方式 * String url 请求接口地址 * JSONObject jsonRequest Get为null,Post传递负载请求参数的Object * Listener<JSONObject> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
JsonObjectRequest request = new JsonObjectRequest(Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject arg0) {
System.out.println("请求成功:" + arg0.toString()); // 输出请求成功返回的JSONObject,这里可以直接进行json解析了
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
System.out.println("请求失败:" + arg0);
}
});
request.setTag("homeJoGet"); // 这个Tag设置的要有意义
MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}
(3)Volley的post请求
首先我们用HashMap封装post请求的参数:
Map<String, String> hashmap = new HashMap<String, String>();
hashmap.put("zhangsan", "12"); // 将传递的参数添加进来
hashmap.put("key", "12");
然后就可以用封装好的参数向URL提交post请求了:
/** * 返回结果类型不确定的情况下 */
private void volleyPost(String url, final HashMap<String, String> hashmap) {
/** * int method 请求方式 * String url 请求接口地址,使用post则请求参数不能写在URL里,而是使用参数化的传递 * 例如url:http://www.demo.com/login/get? * 完整为:url:http://www.demo.com/login/get?zhangsan=12&key=12 * Listener<String> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
StringRequest request = new StringRequest(Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String arg0) {
System.out.println("请求成功:" + arg0); // 输出请求成功的返回结果
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
System.out.println("请求失败:" + arg0);
}
}){
// getParams()方法表示用户在volley中使用post方式请求数据中参数的传递
// volley会自动调用getParams()中传递过来的请求参数
@Override
protected Map<String, String> getParams() {
return hashmap;
}
};
request.setTag("homePost"); // 这个Tag设置的要有意义
MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}
/** * 返回结果类型为JsonObject * 注意:返回结果类型为JsonArray的请求方法和JsonObject类似 */
private void volleyJOPost(String url, final HashMap<String, String> hashmap) {
JSONObject object = new JSONObject(hashmap);
/** * int method 请求方式 * String url 请求接口地址,使用post则请求参数不能写在URL里,而是使用参数化的传递 * 例如url:http://www.demo.com/login/get? * 完整为:url:http://www.demo.com/login/get?zhangsan=12&key=12 * JSONObject jsonRequest 传递负载请求参数的Object * Listener<JSONObject> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
JsonObjectRequest request = new JsonObjectRequest(Method.POST, url, object, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject arg0) {
System.out.println("请求成功:" + arg0.toString()); // 输出请求成功返回的JSONObject,这里可以直接进行json解析了
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
System.out.println("请求失败:" + arg0);
}
});
request.setTag("homeJoPost"); // 这个Tag设置的要有意义
MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}
在我们使用Volley时,要建立一个全局的请求队列,然后我们在建立一个请求,把请求加入到全局队列中,这样app的请求是通过队列管理的,方便我们进行取消某个请求或者取消全部请求。
Volley的生命周期和Activity的生命周期是关联在一起的,可以在Activity销毁时,同时关闭请求。
一般我们将Volley和Activity的生命周期关联的时候,都需要设置我们的Tag标签(通过Tag标签在全局队列中查找),然后在onStop()方法中执行取消请求。
@Override
protected void onStop() {
super.onStop();
MyApplication.getHttpQueue().cancelAll("homeGet"); // 通过给定的tag值,将指定的队列全部关闭
}
全局使用一个方式,可控,可自定义定制需求
首先我们创建自己的请求管理VolleyRequest,其中listener, errorListener还没有创建
public class VolleyRequest {
public static StringRequest request;
public static Context context;
/** * GET请求 * @param context * @param url * @param tag */
public static void RequestGet(Context context, String url, String tag){
MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
StringRequest request = new StringRequest(Method.GET, url, listener, errorListener);
request.setTag(tag);
MyApplication.getHttpQueue().add(request);
MyApplication.getHttpQueue().start();
}
}
接下来创建自定义VolleyInterface抽象类
public abstract class VolleyInterface {
public Context context;
public static Response.Listener<String> listener;
public static Response.ErrorListener errorListener;
public VolleyInterface(Context context, Response.Listener<String> listener,
Response.ErrorListener errorListener){
this.context = context;
this.listener = listener;
this.errorListener = errorListener;
}
public abstract void onMySuccess(String result);
public abstract void onMyError(VolleyError error);
/** * 请求成功 * @return */
public Response.Listener<String> successListener(){
listener = new Response.Listener<String>(){
@Override
public void onResponse(String arg0) {
onMySuccess(arg0);
}
};
return listener;
}
/** * 请求失败 * @return */
public Response.ErrorListener errorListener(){
errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
onMyError(arg0);
}
};
return errorListener;
}
}
接下来我们就可以在VolleyRequest中使用VolleyInterface了:
public class VolleyRequest {
public static StringRequest request;
public static Context context;
/** * GET请求 * @param context * @param url * @param tag * @param vi */
public static void RequestGet(Context context, String url, String tag, VolleyInterface vi){
MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener());
request.setTag(tag);
MyApplication.getHttpQueue().add(request);
MyApplication.getHttpQueue().start();
}
}
到此,自定义get就写好了。
在VolleyRequest中添加自定义post方法:
public class VolleyRequest {
public static StringRequest request;
public static Context context;
/** * GET请求 * @param context * @param url * @param tag * @param vi */
public static void RequestGet(Context context, String url, String tag, VolleyInterface vi){
MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener());
request.setTag(tag);
MyApplication.getHttpQueue().add(request);
MyApplication.getHttpQueue().start();
}
/** * POST请求 * @param context * @param url * @param tag * @param hashmap * @param vi */
public static void RequestPost(Context context, String url, String tag, final HashMap<String, String> hashmap, VolleyInterface vi){
MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener()){
@Override
protected Map<String, String> getParams() {
return hashmap;
}
};
request.setTag(tag);
MyApplication.getHttpQueue().add(request);
MyApplication.getHttpQueue().start();
}
}
/** * 返回结果类型不确定的情况下 */
private void volleyGet(String url) {
VolleyRequest.RequestGet(this, url, "homeGet", new VolleyInterface(this,
VolleyInterface.listener, VolleyInterface.errorListener) {
@Override
public void onMySuccess(String result) {
System.out.println("请求成功:" + result);
}
@Override
public void onMyError(VolleyError error) {
System.out.println("请求失败:" + error.toString());
}
});
}
Volley加载网络图片可以使用ImageRequest或者ImageLoader,监听使用ImageListener,网络图片的显示也可以用NetworkImageView或者ImageView。
public class MainActivity extends Activity {
private ImageView iv_img;
String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_img = (ImageView)findViewById(R.id.iv_img);
/** * String url 图片地址 * Listener<Bitmap> listener 图片请求成功的回调 * int maxWidth 图片大小的压缩处理,设置0则显示原图 * int maxHeight * Config decodeConfig 加载图片的格式 * ErrorListener errorListener 请求失败的回调 */
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap arg0) {
iv_img.setImageBitmap(arg0);
}
}, 200, 200, Config.RGB_565, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
iv_img.setBackgroundResource(R.drawable.ic_launcher); // 显示请求失败的图片
}
});
}
}
(1)创建ImageLoader
public class MainActivity extends Activity {
private ImageView iv_img;
String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_img = (ImageView)findViewById(R.id.iv_img);
/** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
}
}
这里需要使用到imageCache(创建了BitmapCache实例),ImageCache单独使用是起不到缓存作用的,所以还要结合LruCache,接下来自定义一个ImageCache缓存类:
public class BitmapCache implements ImageCache{
public LruCache<String, Bitmap> cache;
public int maxSize = 10*1024*1024; // 10M,定义LruCache最大缓存大小,当超过会启动自动回收
public BitmapCache(){
cache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String arg0) {
return cache.get(arg0);
}
@Override
public void putBitmap(String arg0, Bitmap arg1) {
cache.put(arg0, arg1);
}
}
(2)下来需要创建ImageListener来监听图片的加载过程:
public class MainActivity extends Activity {
private ImageView iv_img;
String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_img = (ImageView)findViewById(R.id.iv_img);
/** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
/** * ImageView view ImageView控件 * int defaultImageResId 默认的加载图片 * int errorImageResId 加载出错的时候显示的图片 */
ImageListener listener = ImageLoader.getImageListener(iv_img,
R.drawable.ic_launcher, R.drawable.ic_launcher);
loader.get(url, listener); // 获取网络图片
}
}
到此使用ImageLoader缓存网络图片就已经完成了。
NetworkImageView是要搭配ImageLoader进行使用的:
public class MainActivity extends Activity {
private NetworkImageView niv_img;
String url = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
niv_img = (NetworkImageView)findViewById(R.id.niv_img);
/** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
niv_img.setDefaultImageResId(R.drawable.ic_launcher); // 设置默认图片
niv_img.setErrorImageResId(R.drawable.ic_launcher); // 设置默认图片
niv_img.setImageUrl(url, loader); // 设置默认图片
}
}