http请求在每个需要网络访问的应用中都是必须的,每次请求中都会 去new一个 HttpRequest,重复的写Handlder的callBack回调却是一件很麻烦的事情,有些页面的请求情况较多的话,往往会使得代码变得很冗长且不易于维护,这样,我们就有必要封装一下了。
我们使用一个统一处理过程,比如请求开始时做什么,结束时做什么,失败时做什么… 把这个过程放在一个类中CommonNet,在类中初始化一个HttpRequest(我使用了XUtil框架所以使用的是HttpUtils,这并不影响流程,换成自己熟悉的请求工具类就可以了),并定义一个send方法来发送请求:
/**
* 网络请求执行过程,app中所有的网络请求都有通过此类执行访问,主要方法是send方法
* @author Administrator
*
*/
public class CommonNet {
NetHander hander;
HttpUtils http = new HttpUtils();
public CommonNet(NetHander hander) {
super();
this.hander = hander;
}
public void send(...){
...
//这个方法比较长,后面再解释
}
}
可能你已经注意到了构造函数的必须参数NetHander了,这是一个接口,定义了请求过程中的所有回调,发送请求的类必须实现这个接口:
/**
* 需要发送请求的Activity都需要实现此类的回调方法
* @author Administrator
*
*/
public interface NetHander {
void netGo(int code,Object pojo,Object obj);
void netStart(int code);
void netEnd(int code);
void netSetFalse(int code,int status,String text);
void netSetFail(int code,int errorCode,String text);
void netSetError(int code,String text);
void netException(int code,String text);
}
最常用的,比如是在Activity发生http请求,那么先初始化一个CommonNet,然后用Activity来实现这个接口:
public class CenterActivity extends Activity implements NetHander{
private CommonNet net = new CommonNet(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_center);
}
@Override
public void netGo(int code, Object pojo, Object obj) {
}
@Override
public void netStart(int code) {
}
@Override
public void netEnd(int code) {
}
@Override
public void netSetFalse(int code,int status,String text) {
}
@Override
public void netSetFail(int code, int errorCode, String text) {
}
@Override
public void netSetError(int code, String text) {
}
@Override
public void netException(int code, String text) {
}
}
然后再使用CommonNet发生请求就可以了,如何请求成功,那么会回调netGo方法,比如我在onCreate中发送一个请求:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_center);
RequestParams params = new RequestParams();
params.addBodyParameter("param1", "hello");
net.send(url, params, 1, CommonPojo.class,null);
}
@Override
public void netGo(int code, Object pojo, Object obj) {
Toast.makeText(this, "httpRequest Success!", Toast.LENGTH_SHORT).show();
}
params 是参数的map集合,包含了所有的请求参数。
这样一个请求就发出去了,下面详细的说下上文忽略掉的send方法:
public void send(final String url,final RequestParams params,final int code,final Class entityClass,final Object obj)
先解释参数:
参数 | 类型 | 解释 |
---|---|---|
url | String | http请求的请求地址 |
params | RequestParams | http请求的请求参数的map集合 |
code | int | 请求标志(标示这个请求的编号) |
entityClass | Class | 请求返回的实体对象(用于自动封装实体类) |
obj | Object | 附加的参数(不进行任何处理,直接传给回调方法,供开发者使用) |
前2个参数就不解释了,大家都懂的,注意解释下后面3个参数的意义和作用
code:
我们使用CommonNet来发生请求的话,请求的回调都在我们用来发送请求的类中(如上例子是Activity),不管发生多少种请求,在这个Activity中回调的都是同一套方法,这样我们在回调方法中就不清楚到底到底该处理哪一次请求的回调,所以我增加了一个code的参数,来给不同的请求编号,
比如:获取验证码的请求为1,登录的请求为2
RequestParams params = new RequestParams();
net.send(url1, params, 1, CommonPojo.class,null);
RequestParams params = new RequestParams();
params.addBodyParameter("username", "liaoinstan");
params.addBodyParameter("password", "123456");
net.send(url2, params, 2, CommonPojo.class,null);
回调:
@Override
public void netGo(int code, Object pojo, Object obj) {
switch (code) {
case 1:
CommonPojo compojo = (CommonPojo)pojo;
Toast.makeText(this, "验证码为:"+compojo.getVcode(), Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
break;
}
}
entityClass:
这个参数表示的是你请求的返回数据的实体类型,在CommonNet的send方法成功后可以进行实体类型的自动封装
比如返回的json数据格式是
{
status:1,
message:"login success",
text:"登录成功"
}
那么你应该新建并传入一个这样的实体类:
public class MyPojo implements Serializable{
private Integer status;
private String text;
private String message;
//必须给出get set方法
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
然后在netGo(int code, Object pojo, Object obj)返回给你,返回给你的是Object类型,需要进行强制转换成你需要的类型,如上的代码中,我传入的是CommonPojo类型,那么就强制转化成CommonPojo类型。
obj:
这个参数主要是为了方便用户传递参数而添加的,CommonNet中不会对它进行任何处理,例如:
我请求前传入一个参数hello:
RequestParams params = new RequestParams();
net.send(url1, params, 1, CommonPojo.class,"hello");
然后在回调中打印它:
@Override
public void netGo(int code, Object pojo, Object obj) {
Toast.makeText(this, (String)obj, Toast.LENGTH_SHORT).show();
}
不要问为啥不保存在外面,要在里面传递,我都说了是为了方便,你总会用得到的。
下面上CommonNet源码:
/**
* 网络请求执行过程,app中所有的网络请求都有通过此类执行访问,主要方法是send方法
* @author Administrator
*
*/
public class CommonNet {
NetHander hander;
HttpUtils http = new HttpUtils();
public CommonNet(NetHander hander) {
super();
this.hander = hander;
}
public void send(final String url,final RequestParams params,final int code,final Class entityClass,final Object obj) {
http.send(HttpRequest.HttpMethod.POST,url, params,
new RequestCallBack<String>() {
@Override
public void onStart() {
LogUtils.d("start");
LogUtils.d("url: " + url);
hander.netStart(code);
}
@Override
public void onLoading(long total, long current,boolean isUploading) {
if (isUploading) {
LogUtils.d("upload: " + current + "/" + total);
} else {
LogUtils.d("reply: " + current + "/" + total);
}
}
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
try {
LogUtils.d("reply: " + responseInfo.result);
JSONTokener jsonParser = new JSONTokener(responseInfo.result);
JSONObject root;
Integer status = null;
String text = "";
try {
root = (JSONObject) jsonParser.nextValue();
if (root.has("status")) status = root.getInt("status");
if (root.has("text")) text = root.getString("text");
} catch (JSONException e) {
e.printStackTrace();
}
Object pojo = new Gson().fromJson(responseInfo.result, entityClass);
System.out.println(pojo);
switch (status) {
case 1:
hander.netGo(code,pojo,obj);
break;
default:
break;
}
if (status<0) {
hander.netSetFalse(code,status,text);
hander.netSetError(code,text);
}
hander.netEnd(code);
} catch (Exception e) {
e.printStackTrace();
hander.netException(code, "未知错误");
}
}
@Override
public void onFailure(HttpException error, String msg) {
try {
LogUtils.d(error.getExceptionCode() + ":" + msg);
hander.netSetFail(code,error.getExceptionCode(),msg);
System.out.println(params);
if (error.getExceptionCode()==0) {
hander.netSetError(code,"网络不太好额~");
}else{
hander.netSetError(code,"服务器异常:"+error.getExceptionCode());
}
hander.netEnd(code);
} catch (Exception e) {
e.printStackTrace();
hander.netException(code, "未知错误");
}
}
});
}
}
上面的请求执行过程可以自行根据需要修改,这里只是符合我的需求:
返回json数据必带status,为1表示成功,其他代表不同的失败情况
下面解释下几个回调方法的区别:
//请求成功后回调
void netGo(int code,Object pojo,Object obj);
//请求开始后回调
void netStart(int code);
//请求结束后回调
void netEnd(int code);
//请求成功状态值返回非1后回调
void netSetFalse(int code,int status,String text);
//请求失败后回调
void netSetFail(int code,int errorCode,String text);
//请求失败或后请求成功状态值返回非1后回调
void netSetError(int code,String text);
//请求过程出现运行时异常后回调
void netException(int code,String text);