Android的Volley的对象传输二次封装
对于volley的对象传输,在开发过程中我们很多时候期望,传输能够直接传输对象,而服务器端也接受到对象,那么多开发对对于安卓的网络,我们选择对其的对象传输进行封装,保证我们传输的对象与接受的对象能够封装完成好,不用进行多余的JSON解析。Volley 的具体配置就不多赘述了。
1.定义一个JsonData 类,这个类是保证与服务器传输的时候,先交互的实体类
public class JsonDataimplements Serializable {
/**
* 数据交换
*/
private static final long serialVersionUID = 8287262158680054979L;
//服务器状态码
private String code;
//服务器返回信息
private String msg;
//返回对象
private T data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String toString(){
return code+":"+msg+":"+data;
}
}
2.定义一个RequestUtils ,在其内部定义一个私有的类,并重新其不封的方法,并设置其http headers并保持与服务器端一直,如果不知道服务器端的headers ,请利用浏览器的调试模式查看自己设置的headers
private class mJsonRequest extends JsonObjectRequest { /** *
@Override
protected ResponseparseNetworkResponse(NetworkResponse response) {
try {
response.headers.put("HTTP.CONTENT_TYPE", "utf-8");//
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
String jsonString = new String(response.data,"utf-8");
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));
}
}
/** * @param method * @param url * @param listener * @param errorListener */
public mJsonRequest(int method, String url, RequestParams params, Listener listener, ErrorListener errorListener) {
super(method, url, params.toString(), listener, errorListener);
}
@Override
public MapgetHeaders() throws AuthFailureError {
Mapheaders = new HashMap();
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
return headers;
}
@Override
public RetryPolicy getRetryPolicy()
{
RetryPolicy retryPolicy = new DefaultRetryPolicy(30 * 1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
return retryPolicy;
}
@Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=" + this.getParamsEncoding();
}
}
}
3.在RequestUtlis中写上一个通用的post传输方式(get 方式可以自己去完善),添加上一般的网络请求失败的状态值。
/**
*
Description:{HTTP POST方法}
*
*@paramurl
*@param
*@paramctx
*@paramrl
*/
publicvoidvolleyPost(String url, RequestParams param,finalContext ctx,finalMResponseListener rl,finalClass type) {
if(!NetUtils.isConnected(ctx)) {
Toast.makeText(ctx,"网络无法连接,请检测您的网络环境", Toast.LENGTH_SHORT).show();
rl.onErrorResponse(null);
return;
}
if(TextUtils.isEmpty(url))
return;
if(TextUtils.isEmpty(url))
return;
String murl =newString(url);
JsonObjectRequestrequest=null;
request=newmJsonRequest(Request.Method.POST, murl, param,newResponse.Listener() {
@Override
public voidonResponse(JSONObject response) {
JsonData data= UtilText.JsonToVo(response,ctx, JsonData.class);
if(!Common.isNull(data)) {
data.setData(UtilText.JsonoVo(data.getData().toString(),ctx,type));
}
rl.onResponse(data);
}
},newResponse.ErrorListener() {
@Override
public voidonErrorResponse(VolleyError volleyerror) {
Log.e("VolleyRequest", volleyerror.toString());
if(volleyerror.getMessage() !=null)
volleyerror.printStackTrace();
NetworkResponse networkResponse = volleyerror.networkResponse;
if(networkResponse !=null) {
intstatusCode = networkResponse.statusCode;
if(statusCode ==404) {
Toast.makeText(ctx,"网络资源没有找到", Toast.LENGTH_SHORT).show();
}
// When Http response code is '500'
else if(statusCode ==500) {
Toast.makeText(ctx,"服务器繁忙,请稍后重试", Toast.LENGTH_SHORT).show();
}
// When Http response code other than 404, 500
else{
Toast.makeText(ctx,"无法连接到服务器,请稍后重试", Toast.LENGTH_SHORT).show();
}
}
else{
Toast.makeText(ctx,"无法连接到服务器,请稍后重试", Toast.LENGTH_SHORT).show();
}
rl.onErrorResponse(volleyerror);
}
});
request.setRetryPolicy(newDefaultRetryPolicy(30*1000,1, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
String urls=request.getUrl();
Map headers=null;
try{
headers=request.getHeaders();
}catch(AuthFailureError authFailureError) {
authFailureError.printStackTrace();
}
String cacheKey =request.getCacheKey();
String bodyContentType=request.getBodyContentType();
ApplicationBase.addToRequestQueue(request);
}
当然在post传输中,我们传入的参数值是以requestParam的方式传入,当然在这传输的时候我们可以适当添加一些,自己APP特有的参数,或者常有必备的参数,如登录的SID(服务器端通过拦截器来判断是否有效),时间戳(骗过缓存,拦截器做一些适当判断,请求时间偏差大于多少就不判断),APPKEY(是否是正常的请求设备)等。
4.编写一个通用的方法,将类转换为requestparam,利用反射
/****
* 将实体转换为requestparam
* */
publicRequestParams getMapParams(Object obj,String name) {
Class clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
if(fields ==null|| fields.length==0) {
returnparams;
}
try{
for(Field field : fields) {
field.setAccessible(true);
Object temp=field.get(obj);
if(Common.isNull(temp)) {
continue;
}
if( tempinstanceofInteger||tempinstanceofString||
tempinstanceofBoolean|| tempinstanceofFloat ||
tempinstanceofLong|| tempinstanceofDouble ||
tempinstanceofShort|| tempinstanceofByte){
if(name!=null){
params.put(name+"."+field.getName(), String.valueOf(temp));
}else{
params.put(field.getName(), String.valueOf(temp));
}
continue;
}else if(tempinstanceofArrayList){
List list=(List)temp;
for(inti=0;i
getMapParams(list.get(i),field.getName()+"["+i+"]");
}
}else if(tempinstanceofArrayMap){
}else{
getMapParams(temp,field.getName());
}
}
}catch(IllegalAccessException e) {
e.printStackTrace();
}catch(IllegalArgumentException e) {
e.printStackTrace();
}
return params;
}
因为在服务器端,采用的springmvc 所以目前的传输方式只采用以上的几种方式。
5.接下来就是测试以上的写法
String url="http://desktop-3bmhc3j:8080/springmvc/user/test1";
User user=newUser();
user.setName("张三");
user.setPassword("密码");
user.setId(123);
Menu menu=newMenu();
menu.setId(321);
List list=newArrayList<>();
list.add(menu);
menu.setId(2);
list.add(menu);
list.add(newMenu());
user.setMenu(menu);
user.setMenuList(list);
RequestUtil.getInstance().volleyPost(url, MapUtils.getInstance().getMapParams(user,null),this,newRequestUtil.MResponseListener() {
public voidonResponse(JsonData json){
Toast.makeText(OnLandAty.this, json.toString() ,Toast.LENGTH_LONG).show();
};
public voidonErrorResponse(VolleyError volleyError){
};
}, User.class);
}
在服务器端我是直接返回传输对象,而返回的也是User对象
最后一点就,我们可能会用Gson转换对象.