在自定义ApiResult以前,先了解本库中默认提供的ApiResult方式,包含code、msg、data三个字段,其中默认code为0表示解析成功,内部是用ApiResult进行数据解析的。
默认ApiResult以下:git
public class ApiResult<T> { private int code;//服务器返回的状态码 private String msg;//服务器返回的成功/失败信息 private T data;//返回的真实数据,也是上层在页面须要展现的信息 public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } public boolean isOk() { //请求成功的判断方法,例如若是指定了code==0是成功,才会回调onSuccess(T t),那么code的非0其它数值都会走失败onError(ApiException e) return code == 0 ? true : false; } }
返回正确的json数据:
返回错误的json数据:github
code:服务器返回的状态码
msg:服务器返回的成功/失败信息
data:返回的真实数据,也是上层在页面须要展现的信息
isOk():请求成功的判断方法,例如指定了code==0是成功才会回调onSuccess(T t),那么code的其它数值都会走失败onError(ApiException e)
每一个公司后台都有本身的一套数据结构规范,数据规范基本都会包含code码,错误信息、返回的数据data。可是他们的字段不必定是code、msg、data这样的三个字段。例如你的结构是error_code(code)、reason(msg)、result(data),那这样就会致使解析失败。而又不想由于几个字段的数据结构不同,全部的解析和业务逻辑从新写一遍。而本库就想让你经过简单的改造,快速的接入,知足你的数据结构解析,因此提出了自定义数据结构的概念。json
注:若是服务器人员在写接口时比较随意彻底没有规范或者没有code、msg这样的结构,直接就是个bean,本库就不支持后期能够考虑支持,暂时没有提供针对非ApiResult结构的支持api
ApiResult类中包含code、msg、data的get和set方法,以覆盖重写的方式来解决,在自定义以前须要先用本身的数据结构对比库中默认的数据结构,同样的不用重复添加或者覆写。最主要的是覆写getCode()、getMsg()、getData()、isOk()四个方法,但不是这四个方法都必须所有覆写看看不一致的地方,哪些不一致就覆写哪些,set相关方法不用覆写。主要解决思想就是把不一致的数据结构,改形成和库中默认的结构一致或者靠拢。浏览器
注意:自定义ApiResult类时TestApiResult<T> extends ApiResult<T>
其中<T>
必须写
举列1:服务器返回的结构是和默认的标准结构如出一辙,只是code码为1表示成功,而库中0表示成功。那么只须要覆写isOk()服务器
public class TestApiResult<T> extends ApiResult<T> { @Override public boolean isOk() { return getCode()==1;//code等于1表示成功,全部覆写isOk() } }
举列2:服务器返回的结构是error_code、reason、result和默认的标准结构彻底不同网络
public class TestApiResult<T> extends ApiResult<T> { int error_code; //对应默认标准ApiResult的code String reason;//对应默认标准ApiResult的msg T result;//对应默认标准ApiResult的data @Override public T getData() {//由于库里使用data字段,而你的结构是result,因此覆写getData()方法,setData()方法不用覆写 return result; } @Override public String getMsg() {//由于库里使用msg字段,而你的结构是reason,因此覆写getMsg()方法,setMsg()方法不用覆写 return reason; } @Override public int getCode() {//由于库里使用code字段,而你的结构是error_code,因此覆写getCode()方法,setCode()方法不用覆写 return error_code; } @Override public boolean isOk() {//由于库里使用code字段,code==0表示成功,可是你的数据结构是error_code==0,因此覆写isOk(),用error_code==0作为判断成功的条件 return error_code == 0;//表示成功 } }
举列3:服务器返回的结构是no,msg,obj结构,其中msg是同样的就不用再特殊处理,no、obj不同须要处理数据结构
注:其它更多情景本身触类旁通
若是返回的字符串很差查看结构,可使用工具分析,例如json格式化工具sojson、bejson、Chrome浏览器插件JSON-Handle、Json Viewer等
连接返回的json数据:工具
看到上面返回的json格式,结合自定义ApiResult原理,定义结构以下:
public class TestApiResult<T> extends ApiResult<T> { int error_code; //对应默认标准ApiResult的code String reason;//对应默认标准ApiResult的msg T result;//对应默认标准ApiResult的data @Override public T getData() { return result; } @Override public String getMsg() { return reason; } @Override public int getCode() { return error_code; } @Override public boolean isOk() { return error_code == 0;//表示成功 } }
注:定义出的TestApiResult<T>
属于公共的,一样的数据结构均可以使用到
自定义数据结构TestApiResult是个通用的结构,实体的data是result,result是泛型T,具体表示什么,须要你本身查看返回json结构,本例中result字段中包含一个data字段,data字段是集合,因此以下:
public class Data { private String content; private String hashId; private int unixtime; private String updatetime; public String getContent() { return content; } public Data setContent(String content) { this.content = content; return this; } public String getHashId() { return hashId; } public Data setHashId(String hashId) { this.hashId = hashId; return this; } public int getUnixtime() { return unixtime; } public Data setUnixtime(int unixtime) { this.unixtime = unixtime; return this; } public String getUpdatetime() { return updatetime; } public Data setUpdatetime(String updatetime) { this.updatetime = updatetime; return this; } @Override public String toString() { return "Data{" + "content='" + content + '\'' + ", hashId='" + hashId + '\'' + ", unixtime=" + unixtime + ", updatetime='" + updatetime + '\'' + '}'; } }
public class Result { private List<Data> data; public void setData(List<Data> data) { this.data = data; } public List<Data> getData() { return data; } @Override public String toString() { return "Result{" + "data=" + data + '}'; } }
自定义的网络请求必须用回调代理execute(CallBackProxy<? extends ApiResult<T>, T> proxy)
来请求网络
EasyHttp.get("http://japi.juhe.cn/joke/content/list.from") .params("key", "f5236a9fb8fc75fac0a4d9b8c27a4e90") .params("page", "1") .params("pagesize", "10") .params("sort", "asc") .params("time", "1418745237") .execute(new CallBackProxy<TestApiResult<Result>, Result>(new ProgressDialogCallBack<Result>(mProgressDialog) { @Override public void onError(ApiException e) { super.onError(e); showToast(e.getMessage()); } @Override public void onSuccess(Result result) { if (result != null) showToast(result.toString()); } }) { });
注:经过以上四个步骤就完成了自定义数据结构网络请求数据,是否是以为写法会有点长,CallBackProxy的泛型参数每次都须要填写,其中TestApiResult是继承ApiResult的,对于一个实际项目来说后台的服务器数据结构是固定的,也就是TestApiResult是固定的,这种方法太麻烦了,那有没有简单的写法,而又不破坏库的使用方式,请看自定义ApiResult高级用法。
上面已经提到过使用自定义网络请求必需要用new CallBackProxy<TestApiResult<Result>, Result>
,会有不少重复的操做,结合上面咱们看下如何简写。讲解以前先说下库中实现方式,网络请求EasyHttp.get()是返回一个GetRequest请求,EasyHttp.post()是返回一个PostRequest请求.若是想让全部的请求execute()方法都自动加上new CallBackProxy<TestApiResult<T>, T>
,就须要修改execute()方法,而execute()方法是在GetRequest和PostRequest中,因此咱们须要分别继承GetRequest和PostRequest,重写execute()方法。具体操做以下:
注:下面代码能够直接拷贝过去使用,其中的TestApiResult修改为本身的ApiResult就能够了
public class CustomGetRequest extends GetRequest { public CustomGetRequest(String url) { super(url); } @Override public <T> Observable<T> execute(Type type) { return super.execute(new CallClazzProxy<TestApiResult<T>, T>(type) { }); } @Override public <T> Observable<T> execute(Class<T> clazz) { return super.execute(new CallClazzProxy<TestApiResult<T>, T>(clazz) { }); } @Override public <T> Subscription execute(CallBack<T> callBack) { return super.execute(new CallBackProxy<TestApiResult<T>, T>(callBack) { }); } }
注:下面代码能够直接拷贝过去使用,其中的TestApiResult修改为本身的ApiResult就能够了
public class CustomPostRequest extends PostRequest { public CustomPostRequest(String url) { super(url); } @Override public <T> Observable<T> execute(Type type) { return super.execute(new CallClazzProxy<TestApiResult<T>, T>(type) { }); } @Override public <T> Observable<T> execute(Class<T> clazz) { return super.execute(new CallClazzProxy<TestApiResult<T>, T>(clazz) { }); } @Override public <T> Subscription execute(CallBack<T> callBack) { return super.execute(new CallBackProxy<TestApiResult<T>, T>(callBack) { }); } }
public class HttpManager { /** * get请求 */ public static GetRequest get(String url) { return new CustomGetRequest(url); } /** * post请求 */ public static PostRequest post(String url) { return new CustomPostRequest(url); } }
HttpManager.get("http://japi.juhe.cn/joke/content/list.from") .params("key", "f5236a9fb8fc75fac0a4d9b8c27a4e90") .params("page", "1") .params("pagesize", "10") .params("sort", "asc") .params("time", "1418745237") .execute(new ProgressDialogCallBack<Result>(mProgressDialog) {//这么实现是否是没有代理了 @Override public void onError(ApiException e) { super.onError(e); showToast(e.getMessage()); } @Override public void onSuccess(Result result) { if (result != null) showToast(result.toString()); } });