以前项目中涉及到Http请求时,一直用的是开源项目asncclient,封装的非常好,使用起来也非常的方便,不再需要自己去管理线程的生命周期,只需要创建一个请求,写一个请求回调即可,13年,google推出了velloy请求框架,功能基本与asyncclient 一样,都是为了简化网络请求编程,但更加灵活,用户可以根据需求自定义不同的请求,关于 Velloy的基本用法就不在说了,网上有许多教程,今天的文章主要讲一下,如何自定义一个带Cookie的并且直接返回Object类型的Request .这一类型的请求也一定是程序 中最常用 的.
很简单的我们就定制了一个直接返回对象并且处理了Cookie 的请求对象.下面看如何使用它去请求服务器.
先看一下,Velloy村身为我们提供了那些请求类型:
1.StringRequest,专门用来处理String类型的数据请求;
2.JsonObjectRequest和JsonArrayRequest,专门用来处理Json对象类型的数据请求
显然,Velloy自带的这几请求类型并不是我们程序中最常用的,无论是返回JsonObject还是String,都需要我们二次处理为对象类型,那么可不可以有一个请求返回的直接就是我们需要的 Entity对象呢,当然是可以的,其次,Velloy为我们提供的请求 都是无Cookie管理的,这显然也是不 完整的.
基于以上两点原因,我们自定义一个再Cookie管理的,直接返回Entity对象的Request.先看一下StringRequest类的源码,源码如下:
public class StringRequest extends Request<String> {
private final Listener<String> mListener;
public StringRequest(int method, String url, Listener<String> listener,
ErrorListener errorListener) {
super(method, url, errorListener);
mListener = listener;
}
public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
}
源码很简单,我们需要注意的也就是parseNetworkResponse这个方法,它是处理服务器返回数据的核心方法,在StringRequest 类的处理中,就是拿到响应体的数据,再根据头中的请求编码格式,转化为一个字符串,所以我们只要在此方法中将返回 的数据转化为我们需要的对象类型既可.下面看代码:
public class ObjectRequest extends Request<Object> {
//请求成功回调
private final Listener<Object> mListener;
//实体对象字节码
private final Class<?> clazz;
//请求参数列表
private final HashMap<String, String> paramsMap;
public ObjectRequest(String url, HashMap<String, String> paramsMap,
Listener<Object> listener, ErrorListener errorListener,
Class<?> clazz) {
super(Method.POST, url, errorListener);
this.mListener = listener;
this.clazz = clazz;
this.paramsMap = paramsMap;
}
/**
* 添加请求头部信息
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
//<span style="color:#FF0000;">如果Application中已经有了Cookie信息,带Cookie请求.</span>
Map<String, String> map = new HashMap<String, String>();
if (VolleyApplication.getInstance().getCookie() != null) {
map.put("Cookie", VolleyApplication.getInstance().getCookie());
}
return super.getHeaders();
}
/**
* 添加请求参数方法
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return paramsMap;
}
@Override
protected Response<Object> parseNetworkResponse(NetworkResponse response) {
for (String s : response.headers.keySet()) {
if (s.contains("Set-Cookie")) {
/**
*<span style="color:#FF0000;"> 保存到全局Cookie变量中,后续的请求直接取出使用</span>
*/
VolleyApplication.getInstance().setCookie(
response.headers.get(s));
break;
}
}
try {
String string = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
/<span style="color:#FF0000;">/将返回的Json字符串直接转化为对象</span>
return Response.success(
ResponseEntityToModule.parseJsonToModule(string, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(Object response) {
mListener.onResponse(response);
}
}
很简单的我们就定制了一个直接返回对象并且处理了Cookie 的请求对象.下面看如何使用它去请求服务器.
1.Activity中代码:
public class MainActivity extends Activity implements Listener<Object>,
ErrorListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestCenter.getInstance().userLogin("focusgbbuyer", "focus1234",
this, this);
}
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
@Override
public void onResponse(Object response) {
Log.e("Response", "Session:"+((User) response).sessionid + "\r\nCookie:"
+ VolleyApplication.getInstance().getCookie());
}
}
2.RequestCenter中是所有请求的集合:
public class RequestCenter {
private static RequestCenter instance = null;
private RequestQueue mQueue;
private VolleyApplication application;
private RequestCenter() {
application = VolleyApplication.getInstance();
mQueue = application.getRequestQueue();
}
public static RequestCenter getInstance() {
if (instance == null) {
synchronized (RequestCenter.class) {
if (instance == null) {
instance = new RequestCenter();
}
}
}
return instance;
}
/**
* 用户登录请求
*
* @param username
* 用户名
* @param password
* 密码
* @param context
* @param lisener
* 登录结果回调
*/
public void userLogin(String username, String password,
Listener<Object> listener, ErrorListener errorListener) {
HashMap<String, String> params = new HashMap<String, String>();
params.put("loginId", username);
params.put("password", password);
params.put("region", "MIC for Buyer Android");
ObjectRequest stringRequest = new ObjectRequest(
UrlConstants.USER_LOGIN, params, listener, errorListener,
User.class);
mQueue.add(stringRequest);
}
}
使用单例确保这些大对象,只有一个实例既可.经过这样一封装,使用起来很简单了.下面看服务器的返回数据.
好了,完全符合我们的要求,有新需求还可以在上面直接修改,下面是Demp源码: