android开发游记:封装http请求,快速实现网络加载

来源:互联网 发布:mmd常用姿势数据下载 编辑:程序博客网 时间:2024/06/10 23:48

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);
0 0