一、简介
Volley是Google在2003年的I/O大会上推出的通信框架,结合了AsyncHttpClient和Universal-Image-Loader的优点,简化了http的使用和异步加载图片的使用步骤。Android中的Http实现主要有HttpUrlConnection和HttpClient两种,关于二者的选择Google在Blog中表示推荐在姜饼小人(API level = 9)及以上的版本中使用Java的HttpUrlConnection,而在之前的版本使用Apache的HttpClient,这在Volley这个框架中也有明确的体现。
获取Volley的方式: https://android.googlesource.com/platform/frameworks/volley
我们可以直接下载jar包,拷贝到libs中。
二、使用场景
1.数据量小、请求频繁。
备注:不适用于文件的上传和下载。
三、使用示例
1、简单的请求
Http的通信最主要的部分应该就是发出请求和接收响应了,所以Volley的比较核心的一个类就是RequestQueue,一个请求队列。它负责管理工作线程,读写缓存,和解析、分发响应(具体操作还是由具体的类实现),即将发出的Http请求都会首先聚集在这里等待工作线程来实现请求。Volley进行Http通信的简单步骤:
①获取RequestQueue
②实例化一个Request
③将Request加入RequestQueue,等待工作线程执行。
Request的几个子类:
①public StringRequest(int method, String url, Listener listener,ErrorListener errorListener);
参数说明:从左到右分别是请求方法(都封装在Request中的Method接口内),请求URL,响应监听接口实例,错误监听接口实例。执行该方法,在响应后获得的返回数据是一个字符串。
②public JsonObjectRequest(int method, String url, JSONObject jsonRequest,Listener listener, ErrorListener errorListener);
public JsonObjectRequest(String url, JSONObject jsonRequest, Listener listener,ErrorListener errorListener);
参数说明:如果是GET请求的话,jsonRequest传入null就可以了,否则在未指明请求方法的情况下(也就是第二个构造函数)会默认为POST请求。执行该方法,在响应后获得的返回数据是一个JSONObject对象。
③public JsonArrayRequest(String url, Listener listener, ErrorListener errorListener);
执行该方法,在响应后获得的返回数据是一个JSONArray数组。
④public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight,Config decodeConfig, Response.ErrorListener errorListener);
执行该方法,在响应后获得的返回数据是一个Bitmapt图片,可以很方便的设置给ImageView控件。
下面给出几个请求的示例
①GET方式
private void stringRequest(String url) {
final ProgressDialog progressDialog = ProgressDialog.show(this,"Title", "Loading...");
RequestQueue queue = Volley.newRequestQueue(this);
// 根据给定的URL新建一个请求
StringRequest stringRequest = new StringRequest(Request.Method.GET,
url, new Response.Listener() {
@Override
public void onResponse(Object response) {
if (progressDialog.isShowing()&& progressDialog != null) {
progressDialog.dismiss();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (progressDialog.isShowing()&& progressDialog != null) {
progressDialog.dismiss();
}
}
});
queue.add(stringRequest);
}
②POST方式,普通方式提交参数。
private void postRequestWithParams(String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(Request.Method.POST,
url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Map<String, String> getParams() {
// 在这里设置需要post的参数
Map<String, String> map = new HashMap<String, String>();
map.put("name", "value1");
map.put("password", "value2");
return map;
}
};
requestQueue.add(stringRequest);
}
③POST方式,提交的参数为JSONObject类型。但这个看服务器是否要支持这种请求方式,比如常见的spring mvc服务端,就很难支持json的请求方式。
private void postRequestWithJSON(String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
Map<String, String> params = new HashMap<String, String>();
params.put("name", "value1");
params.put("password", "value2");
JSONObject jsonObject = new JSONObject(params);
JsonRequest<JSONObject> jsonRequest = new JsonObjectRequest(
Method.POST, url, jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
//
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//
}
}) {
@Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
requestQueue.add(jsonRequest);
}
④POST请求,继承Request类,自定义Request的请求参数列表。
NormalPostRequest类
package com.example.volleydemo;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class NormalPostRequest extends Request<JSONObject> {
private Map<String, String> mMap;
private Listener<JSONObject> mListener;
public NormalPostRequest(String url, Listener<JSONObject> listener,
ErrorListener errorListener, Map<String, String> map) {
super(Request.Method.POST, url, errorListener);
mListener = listener;
mMap = map;
}
// mMap是已经按照前面的方式,设置了参数的实例
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return mMap;
}
// 此处因为response返回值需要json数据,和JsonObjectRequest类一样即可
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString),HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
@Override
protected void deliverResponse(JSONObject response) {
mListener.onResponse(response);
}
}
调用自定义的类,进行POST请求
//可以自定义传入的参数
private void postRequestWithCustom(String url,Map<String,String> params){
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
Request<JSONObject> request = new NormalPostRequest(url,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
//
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//
}
}, params);
requestQueue.add(request);
}
2.请求图片
Volley提供了多种请求图片的方式
①ImageRequest能够处理单张图片,返回bitmap。
private void requestImage(final ImageView imageView){
RequestQueue requestQueue = Volley.newRequestQueue(this);
ImageRequest imgRequest=new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap arg0) {
imageView.setImageBitmap(arg0);
}
}, 300, 200, Config.ARGB_8888, new ErrorListener(){
@Override
public void onErrorResponse(VolleyError arg0) {
//
}
});
requestQueue.add(imgRequest);
}
②使用ImageLoader。
实例化一个ImageLoader需要一个RequestQueue,还有一个ImageCache,这是一个ImageLoader内部定义的接口,用来实现L1缓存——内存缓存(Volley在RequestQueue中已经实现了L2缓存——文件缓存)。ImageLoader中并没有对传入的ImageCache在使用前判空的代码,传null进去会出错的。如果实在不想弄内存缓存,实现一个什么都不做的ImageCache就好了。
private void requestImageWithImageLoader(String url,ImageView iv,int default_image, int error_image){
RequestQueue queue = Volley.newRequestQueue(this);
ImageLoader loader = new ImageLoader(queue, new ImageCache() {
@Override
public void putBitmap(String url, Bitmap bitmap) {
}
@Override
public Bitmap getBitmap(String url) {
return null;
}
});
//default_image是正在加载图片时占位用的
//error_image是加载不成功时显示的图片
loader.get(url, ImageLoader.getImageListener(iv,default_image, error_image));
}
③使用NetworkImageView请求并显示图片
NetworkImageView继承自ImageView。
private void requestImageWithNetworkImageView(String url,NetworkImageView networkImageView,int defult_image,int error_image){
//networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
networkImageView.setDefaultImageResId(defult_image);
networkImageView.setErrorImageResId(error_image);
networkImageView.setImageUrl(url, new ImageLoader(queue, new ImageCache() {
@Override
public void putBitmap(String url, Bitmap bitmap) {
}
@Override
public Bitmap getBitmap(String url) {
return null;
}
}));
}
3.取消请求
Activity里面启动了网络请求,而在这个网络请求还没返回结果的时候,Activity被结束了,此时如果继续使用其中的Context等,除了无辜的浪费CPU,电池,网络等资源,有可能还会导致程序crash,所以,我们需要处理这种一场情况。使用Volley的话,我们可以在Activity停止的时候,同时取消所有或部分未完成的网络请求。Volley里所有的请求结果会返回给主进程,如果在主进程里取消了某些请求,则这些请求将不会被返回给主线程。Volley支持多种request取消方式。
①取消指定的request
@Override
public void onStop() {
for (Request request : queue) {
if(...){
request .cancel();
}
}
}
②取消队列中的所有请求
@Override
protected void onStop() {
super.onStop();
queue.cancelAll(this);
}
③可以根据RequestFilter或者Tag来终止某些请求
@Override
rotected void onStop() {
super.onStop();
queue.cancelAll( new RequestFilter() {});
//queue.cancelAll(new Object());
四、自定义缓存类
1.自定义的一个图片缓存类
package com.example.volleydemo;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;
public class LruImageCache implements ImageCache{
private static LruCache<String, Bitmap> mMemoryCache;
private static LruImageCache lruImageCache;
private LruImageCache(){
// Get the Max available memory,set cacheSize 1/8
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 8;
//cacheSize:缓存区大小,也可以设置为固定值10*1024*1024=10MB
mMemoryCache = new LruCache<String, Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap bitmap){
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
public static LruImageCache instance(){
if(lruImageCache == null){
lruImageCache = new LruImageCache();
}
return lruImageCache;
}
@Override
public Bitmap getBitmap(String arg0) {
return mMemoryCache.get(arg0);
}
@Override
public void putBitmap(String arg0, Bitmap arg1) {
if(getBitmap(arg0) == null){
mMemoryCache.put(arg0, arg1);
}
}
}
未完待续…