Volley提供了特别强的扩展机制,我们可以很轻松地定制出任意类型的Request。目前市场的Android客户端与服务端进行数据通信用到的数据类型90%以上都是json。而搭配Google的Gson会让json数据解析变得更加的简单。
- 自定义GsonRequest
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.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;
import java.util.Map;
/**
* volley请求json数据的封装
* * Created by changj on 16/6/14.
*/
public class GsonRequest<T> extends Request<T>{
/**
* gson实例用于解析请求回调的json数据
*/
private final Gson gson = new Gson();
/**
* 解析json对应的泛型对象
*/
private final Class<T> clazz;
/**
* 请求成功的回调
*/
private final Response.Listener<T> listener;
/**
* 请求服务器时必须携带的请求头参数,密钥、token等
*/
private static Map<String,String> mHeader = new Hashtable<String,String>();
/**
* 设置请求头参数
*/
static {
mHeader.put("token","Suso56");
//mHeader.put("APP-Secret","afafaffgrgth4");
}
/**
* 定制请求参数
*
* @param method 请求方式,GET、POST等
* @param url 请求地址
* @param appendHeader 请求头参数
* @param clazz 最终json数据转化对应的对象
* @param listener 成功回调
* @param errorlistener 失败回调
*/
public GsonRequest(int method, String url, Map<String, String> appendHeader,Class<T> clazz, Response.Listener<T> listener,Response.ErrorListener errorlistener) {
super(method, url, errorlistener);
this.clazz = clazz;
this.listener = listener;
if (appendHeader != null){
mHeader.putAll(appendHeader);
}
}
/**
* 重载getHeaders()方法,重构请求头参数
*
* @return
* @throws AuthFailureError
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return mHeader;
}
/**
* 解析服务器响应的数据
*
* @param networkResponse
* @return
*/
@Override
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) {
try {
/**
* 得到返回的数据
*/
String jsonStr = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers));
Log.d("VOLLEY",jsonStr);
/**
* 将数据转化对象
*/
return Response.success(gson.fromJson(jsonStr,clazz), HttpHeaderParser.parseCacheHeaders(networkResponse));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
/**
* 解析成功响应的数据的最终回调
*
* @param response
*/
@Override
protected void deliverResponse(T response) {
try {
if (listener != null) {
listener.onResponse(response);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
- 封装RequestQueue
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import com.changj.pearl.application.MyApplication;
/**
* volley请求队列的封装
* :
*
* Created by admin on 16/6/14.
*/
public class VolleyRequestQueue {
/**
* 单例
*/
private static VolleyRequestQueue instance;
/**
* 请求队列
*/
private RequestQueue mRequestQueue;
/**
* 图片加载ImageLoader
*/
private ImageLoader mImageLoader;
private VolleyRequestQueue(){
mRequestQueue = getRequestQueue();
mImageLoader = getImageLoader();
}
/**
* 异步获取单利
*
* @return
*/
public static synchronized VolleyRequestQueue getInstance(){
if (instance == null){
instance = new VolleyRequestQueue();
}
return instance;
}
/**
* 获取volley请求队列
*
* @return
*/
public RequestQueue getRequestQueue(){
if (mRequestQueue == null){
/**
* MyApplication.getInstance()返回当前进程的全局应用上下文
* 使用场景:生命周期独立于当前上下文的全局上下文,即它的存活时间绑定在整个程序进程而不是当前某个组件。
*/
mRequestQueue = Volley.newRequestQueue(MyApplication.getInstance());
}
return mRequestQueue;
}
/**
* 获取ImageLoader
*
* @return
*/
public ImageLoader getImageLoader(){
mImageLoader = new ImageLoader(getRequestQueue(),new BitmapCache());
return mImageLoader;
}
/**
* add to queue
*
* @param request
* @param <T>
*/
public <T> void addToReuestQueue(Request<T> request){
getRequestQueue().add(request);
}
/**
* remove from queue
*
* @param tag
*/
public void cancelRequestFromQueue(Object tag){
getRequestQueue().cancelAll(tag);
}
}
其中需要Application的全局变量(注意,别忘了在AndroidManifest.xml中声明)和封装图片缓存的BitmapCache()
类,分别如下:
public class MyApplication extends Application{
private static MyApplication instance;
public static MyApplication getInstance(){
if (instance == null){
synchronized (MyApplication.class){
if (instance == null){
instance = new MyApplication();
}
}
}
return instance;
}
@Override
public void onCreate() {
instance = this;
super.onCreate();
}
}
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.toolbox.ImageLoader;
/**
* 借助Android提供的LruCache功能实现图片缓存
* Created by admin on 16/6/21.
*/
public class BitmapCache implements ImageLoader.ImageCache{
private LruCache<String, Bitmap> mCache;
public BitmapCache() {
//缓存图片的大小设置为10M
int maxSize = 10 * 1024 * 1024;
mCache = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
}
- 封装HttpUtil工具类
public class HttpUtil {
/**
* GET请求
*
* @param url
* @param appendHeader
* @param clazz
* @param listener
* @param errorlistener
* @param <T>
*/
public static <T>void getJsonRequest(String url, Map<String, String> appendHeader, Class<T> clazz, Response.Listener<T> listener, Response.ErrorListener errorlistener){
GsonRequest<T> request = new GsonRequest<>(Request.Method.GET, url, appendHeader, clazz, listener, errorlistener);
request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f));
VolleyRequestQueue.getInstance().addToReuestQueue(request);
}
/**
* POST请求
*
* @param url
* @param appendHeader
* @param clazz
* @param listener
* @param errorlistener
* @param <T>
*/
public static <T>void postJsonRequest(String url, Map<String, String> appendHeader, Class<T> clazz, Response.Listener<T> listener, Response.ErrorListener errorlistener){
GsonRequest<T> request = new GsonRequest<>(Request.Method.POST, url, appendHeader, clazz, listener, errorlistener);
request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f));
VolleyRequestQueue.getInstance().addToReuestQueue(request);
}
/**
* 加载网络图片
*
* @param imageUrl 图片url
* @param view 显示图片的view控件
* @param loadingImageId 加载中显示的图片id
* @param failImageId 加载失败显示的图片id
*/
public static void loadImage(String imageUrl, ImageView view, int loadingImageId, int failImageId){
//获取ImageLoader
ImageLoader imageLoader = VolleyRequestQueue.getInstance().getImageLoader();
//获取ImageListener
ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(view, loadingImageId, failImageId);
/**
* 加载图片:如需设置图片大小,imageLoader.get(imageUrl,imageListener,int maxWidth,int maxHeight);
*/
imageLoader.get(imageUrl,imageListener);
}
}
- 使用实例
请求的json数据如下:
{
"status":"1",
"data":"{"phone":"13083060621","name":"changj","pass":"123456"}",
"msg":"OK"
}
上述json数据对应的model对象如下:
import com.changj.pearl.http.GsonUtils;
import com.google.gson.Gson;
/**
* <p>
* 封装了业务逻辑的JavaBean(服务端返回的数据)<其中data部分不是数组>
* </p>
* Created by admin on 16/6/14.
*/
public class BaseServerModel {
private int status;
private String data;
private String msg;
/**
* 数据返回成功
*
* @return
*/
public boolean isSuccess() {
return getStatus() == 1;
}
public <E> E parseData(Class<E> clazz) {
E e = null;
try {
Log.d("VOLLEY",getData());
e = new Gson().fromJson(getData(),clazz);
} catch (Exception e1) {
try {
e = clazz.newInstance();
} catch (Exception e2) {
}
}
return e;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
上述json数据data部分对应的model对象如下:
public class User implements Serializable{
private String phone;
private String name;
private String pass;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
请求代码如下:
HttpUtil.getJsonRequest(url, null, BaseServerModel.class, new Response.Listener<BaseServerModel>() {
@Override
public void onResponse(BaseServerModel baseServerModel) {
User user = baseServerModel.parseData(User.class);
Toast.makeText(getActivity(), "姓名:"+user.getName()+"|手机:"+user.getPhone()+"|密码:"+user.getPass(), Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getActivity(), "error", Toast.LENGTH_SHORT).show();
}
});