今天准备为大家带来一个Volley框架的网络请求实现,个人认为用起来还是比较爽,各位大神有什么见解,希望可以告知我下,谢谢!
咱们写Android的,基本上在敲代码要进行各种操作的时候,都是操作对象,那么我们在一个请求中,如果直接服务器端返回的就是一个对象,那么你是不是用起来就会感觉很爽!好,接下来我们上正菜!
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import java.util.Map;
public class HttpHelper {
private Context context;
private ImageLoader loader;
private RequestQueue queue;
private String baseUrl = "";
/**
* 构造方法
*
* @param context 上下文
*/
public HttpHelper(Context context) {
this.context = context;
if (queue == null) {
this.queue = Volley.newRequestQueue(this.context);
}
}
/**
* 图片
*
* @return
*/
public ImageLoader getImageLoader() {
if (loader == null) {
this.loader = new ImageLoader(queue, new ImgCache());
}
return loader;
}
/**
* 错误监听
*/
public Response.ErrorListener errorListener = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(context, VolleyErrorHelper.getMessage(volleyError), Toast.LENGTH_SHORT).show();
}
};
public void PostObject(String url, Map<String, String> params, Class clazz, Response.Listener listener, Response.ErrorListener nowErrorListener) {
PostObjectRequest request = new PostObjectRequest(url, params, clazz, listener, nowErrorListener);
queue.add(request);
}
public void PostArray(String url, Map<String, String> params, Class clazz, Response.Listener listener, Response.ErrorListener nowErrorListener) {
PostArrayRequest request = new PostArrayRequest(url, params, clazz, listener, nowErrorListener);
queue.add(request);
}
public void PostMap(String url, Map<String, String> params, Response.Listener listener, Response.ErrorListener nowErrorListener) {
PostMapRequest request = new PostMapRequest(url, params, listener, nowErrorListener);
queue.add(request);
}
public void PostObject(String url, Map<String, String> params, Class clazz, Response.Listener listener) {
PostObjectRequest request = new PostObjectRequest(url, params, clazz, listener, errorListener);
queue.add(request);
}
public void PostArray(String url, Map<String, String> params, Class clazz, Response.Listener listener) {
PostArrayRequest request = new PostArrayRequest(url, params, clazz, listener, errorListener);
queue.add(request);
}
public void PostMap(String url, Map<String, String> params, Response.Listener listener) {
PostMapRequest request = new PostMapRequest(url, params, listener, errorListener);
queue.add(request);
Log.d("main", "POST request");
}
public void GetObject(String url, Class clazz, Response.Listener listener, Response.ErrorListener nowErrorListener) {
GetObjectRequest request = new GetObjectRequest(url, clazz, listener, nowErrorListener);
queue.add(request);
}
public void GetArray(String url, Class clazz, Response.Listener listener, Response.ErrorListener nowErrorListener) {
GetArrayRequest request = new GetArrayRequest(url, clazz, listener, nowErrorListener);
queue.add(request);
}
public void GetMap(String url, Response.Listener listener, Response.ErrorListener nowErrorListener) {
GetMapRequest request = new GetMapRequest(url, listener, nowErrorListener);
queue.add(request);
}
public void GetObject(String url, Class clazz, Response.Listener listener) {
GetObjectRequest request = new GetObjectRequest(url, clazz, listener, errorListener);
queue.add(request);
}
public void GetArray(String url, Class clazz, Response.Listener listener) {
GetArrayRequest request = new GetArrayRequest(url, clazz, listener, errorListener);
queue.add(request);
}
public void GetMap(String url, Response.Listener listener) {
GetMapRequest request = new GetMapRequest(url, listener, errorListener);
queue.add(request);
}
public void stop() {
queue.stop();
}
public void start() {
queue.start();
}
public void cancelAll() {
queue.cancelAll(context);
}
public void special(Request request) {
queue.add(request);
}
}
这是最基本的httphelper,好的ok,我知道这不是重点,但这是咱们helper类啊,如果没有他,就什么都干不了,虽然大家都会写,但是我们也需要为比我还新的新人着想嘛!
下面是ImageLoader类,知道的直接略过,不知道的只需要知道这个类主要帮咱们实现了图片缓存,如果以后有机会,再说!
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.toolbox.ImageLoader;
public class ImgCache implements ImageLoader.ImageCache{
private LruCache<String,Bitmap> lruCache;
/**
* 构造方法
*/
public ImgCache(){
if (lruCache==null){
/** 获取系统分配给每个应用程序的最大内存,并把系统内存的1/5分配给lruCache */
int maxSize=(int)(Runtime.getRuntime().maxMemory()/1024/5);
lruCache=new LruCache<String,Bitmap>(maxSize){
/** 测量Bitmap的大小 */
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}
};
}
}
@Override
public Bitmap getBitmap(String s) {
return lruCache.get(s);
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
lruCache.put(s,bitmap);
}
}
请求出现问题的时候,就出现这个类了,忘了当时在哪找的,欢迎主人来认领,如果侵犯了您的权益,请您联系我!
package com.smoothframe.http;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NoConnectionError;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
public class VolleyErrorHelper {
public static String getMessage(Object error) {
if (error instanceof TimeoutError) {
return "网络不给力~!";
} else if (isServerProblem(error)) {
return "服务器异常~!";
} else if (isNetWorkPrlblem(error)) {
return "网络异常~!";
}
return "网络异常,请稍后再试~!";
}
/**
* 无网络连接
* @param error
* @return
*/
private static boolean isNetWorkPrlblem(Object error){
return (error instanceof NetworkError)||(error instanceof NoConnectionError);
}
/**
* 服务器的响应的一个错误,最有可能的4xx或5xx HTTP状态代码
* @param error
* @return
*/
private static boolean isServerProblem(Object error){
return (error instanceof ServerError)||(error instanceof AuthFailureError);
}
}
ok,看了上面这么多东西,是不是觉得没有用,我也这么觉得,接下来上个汤吧!
import com.alibaba.fastjson.JSON;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
public class PostArrayRequest extends Request<List> {
private Response.Listener<List> listener;
private Map<String,String> params;
private Class clazz;
public PostArrayRequest(String url, Map<String, String> params, Class clazz, Response.Listener<List> listener, Response.ErrorListener errorListener) {
super(Method.POST,url, errorListener);
this.listener=listener;
this.params=params;
this.clazz=clazz;
}
protected Response<List> parseNetworkResponse(NetworkResponse response) {
List list=null;
try {
String json=new String(response.data,"utf-8");
if (!json.isEmpty()&&!json.matches("^\\[null\\]$")) {
list=(List) JSON.parseArray(json, clazz);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Response.success(list, HttpHeaderParser.parseCacheHeaders(response));
}
protected void deliverResponse(List response) {
listener.onResponse(response);
}
@Override
public void deliverError(VolleyError error) {
super.deliverError(error);
}
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
}
好的 我们来仔细看一下这个类,该类我们继承了Request,然后呢写了一个构造函数!
public PostArrayRequest(String url, Map<String, String> params, Class clazz, Response.Listener<List> listener, Response.ErrorListener errorListener) {
super(Method.POST,url, errorListener);
this.listener=listener;
this.params=params;
this.clazz=clazz;
}
现在来解释下,这都是什么东西,
String url //顾名思义,请求地址
Map<String, String> params //我们的请求参数,采用了键值对的方式
Class clazz //类类型 有啥用呢,往下再看
Response.Listener<List> listener //请求返回监听
Response.ErrorListener errorListener //请求错误监听
ok,几个参数我们都知道了,但是都是干吗用的呢?
super(Method.POST,url, errorListener);
好的这个super已经帮我们排除掉了两个参数,一个请求地址,一个错误监听,源码中是如何实现的,我们先不管,反正现在我不用在关心这两个参数了.
接下来看
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
好的,咱们重写了一下getParams,从方法名也能看出来,这个是获取参数的,咱们把上面的params直接放到这里,ok,参数已经设置好了.想知道内部原理的的,可以点进去看看,很简单的代码.
接下来我们在搞定 Response.Listener listener 这个参数
protected void deliverResponse(List response) {
listener.onResponse(response);
}
好的,这个监听的回调需要我们自己调用,放在这里ok.
那么接下来就剩最后一个 Class clazz 了
恩这个是干什么的呢 ? 我们仔细看一下
protected Response<List> parseNetworkResponse(NetworkResponse response) {
List list=null;
try {
String json=new String(response.data,"utf-8");
if (!json.isEmpty()&&!json.matches("^\\[null\\]$")) {
list=(List) JSON.parseArray(json, clazz);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Response.success(list, HttpHeaderParser.parseCacheHeaders(response));
}
这个方法,其实就是我们的请求已经发送完成并且服务器端接收后给我们返回参数时,就调用的我们这个方法,数据通过 response.data 存储,我们先把他转成了String,然后进行一些基本的判断,这时,细心的你一定发现了
list=(List) JSON.parseArray(json, clazz);
yes,这个类类型就是在这使用的,在这里我使用的是fastjson这个东东来转的,当然,你喜欢gson也可以,随你喜欢!
然后我们就要把结果抛出来了
return Response.success(list, HttpHeaderParser.parseCacheHeaders(response));
恩ok,这里抛出去,deliverResponse一调用, 我们在监听的回调中,就可以得到这个list对象了!
ok,我们的一个自定义request请求,就写出来了,相信聪明的你一定也知道HttpHelper类里面的
PostObjectRequest,PostMapRequest,GetObjectRequest,GetArrayRequest,GetMapRequest,GetObjectRequest,GetArrayRequest,GetMapRequest这些东东里面究竟是什么了吧!
看到这里有的看官要说了,这tmd什么玩意,我的服务端给我返回这种固定数据类型的机会太少了,你不是说操作对象么,对象在哪里,这个完全没什么卵用嘛! ok,ok,别急,现在上烤鸭!
细心的看官肯定注意到这段代码了
public void special(Request request) {
queue.add(request);
}
简单来说,这个也是我们用来在队列里加入一个request的,这个咱们都知道,但是加入的request,这次有变化哦!
import android.content.Context;
import com.alibaba.fastjson.JSON;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.htxt.yourcard.android.Utils.MyLog;
import com.htxt.yourcard.android.Utils.RSASignature;
import com.htxt.yourcard.android.view.PromptDialog;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class SignatureRequest<T> extends Request<T> {
private Response.Listener<T> listener;
private LinkedHashMap<String, String> params;
private Class<T> clazz;
private Context context;
private String url;
public SignatureRequest(String url, LinkedHashMap<String, String> params, Class<T> clazz, Response.Listener<T> listener, Response.ErrorListener errorListener, Context context) {
super(Method.POST, url, errorListener);
this.url = url;
this.listener = listener;
this.params = params;
this.clazz = clazz;
this.context = context;
}
protected Response<T> parseNetworkResponse(NetworkResponse response) {
T t = null;
try {
String json = new String(response.data, "utf-8");
if (!"".equals(json) && json != null) {
t = JSON.parseObject(json, clazz);
} else {
MyLog.d("main", "失败");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return Response.success(t, HttpHeaderParser.parseCacheHeaders(response));
}
protected void deliverResponse(T response) {
listener.onResponse(response);
}
}
好的,大家来看一下这个类,熟悉不熟悉,眼熟不眼熟?
是的,除了
SignatureRequest<T> ,Request<T> , private Class<T> clazz;
这些地方,简直和之前的PostArrayRequest一模一样有木有!
好的,经过上面的介绍,大家已经对这个request有一定了解了,但是我们之前直接设置了泛型为List,而这里,没有设置泛型是什么,那这种时候,我们是不是就可以 嘿嘿嘿!
ok看效果!
假设服务端返回的数据像这样
{"name":"bigwhite","age":"18"}
那么我们在android端要用一个实体类来保存的时候是不是就要像这样?
public class Handsome {
private String name;
private String age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(String age) {
this.age = age;
}
public String getAge() {
return age;
}
}
好的那么我们实际使用的时候来了!
HashMap<String, String> params = new HashMap<>();
params.put("condition", "请给我一个帅哥");
SignatureRequest request = new SignatureRequest("http://www.handsomeBoy.com", params, Handsome.class,
new Response.Listener() {
@Override
public void onResponse(Object o) {
Handsome handsome = (Handsome)o;
//这里拿到了对象,你想干什么呢
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
//哦不,出错了,交给VolleyErrorHelper.getMessage(volleyError)判断处理
showDialog(null, VolleyErrorHelper.getMessage(volleyError), true);
}
}, this);
httpHelper.special(request);//别忘了把这个请求放进请求队列里.
ok,这次真的完事了,现在开始,我们在继续需要跟服务器请求其他数据的时候,根据数据文档,创建出对应的实体类,然后把类类型和参数这些的传到我们的request里面,当服务器返回的时候,我们什么都不用管,只要把对象拿到进行操作就好了,.好了到这里就结束了,不知道这样的方法你有没有用的很爽?
ps:第一次写,之前也没这方面经验,如果有任何问题请喷请指正