github源碼地址:https://github.com/zhou-you/RxEasyHttp
RxEasyHttp庫默認(rèn)ApiResult簡(jiǎn)介
在自定義ApiResult之前,先了解本庫中默認(rèn)提供的ApiResult方式,包含code、msg、data三個(gè)字段,其中默認(rèn)code為0表示解析成功,內(nèi)部是用ApiResult進(jìn)行數(shù)據(jù)解析的。
默認(rèn)ApiResult如下:
public class ApiResult<T> {
private int code;//服務(wù)器返回的狀態(tài)碼
private String msg;//服務(wù)器返回的成功/失敗信息
private T data;//返回的真實(shí)數(shù)據(jù),也是上層在頁面需要展示的信息
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() {
//請(qǐng)求成功的判斷方法,例如如果指定了code==0是成功,才會(huì)回調(diào)onSuccess(T t),那么code的非0其它數(shù)值都會(huì)走失敗onError(ApiException e)
return code == 0 ? true : false;
}
}
返回正確的json數(shù)據(jù):
返回錯(cuò)誤的json數(shù)據(jù):
code:服務(wù)器返回的狀態(tài)碼
msg:服務(wù)器返回的成功/失敗信息
data:返回的真實(shí)數(shù)據(jù),也是上層在頁面需要展示的信息
isOk():請(qǐng)求成功的判斷方法,例如指定了code==0是成功才會(huì)回調(diào)onSuccess(T t),那么code的其它數(shù)值都會(huì)走失敗onError(ApiException e)
為什么需要自定義ApiResult
每個(gè)公司后臺(tái)都有自己的一套數(shù)據(jù)結(jié)構(gòu)規(guī)范,數(shù)據(jù)規(guī)范基本都會(huì)包含code碼,錯(cuò)誤信息、返回的數(shù)據(jù)data。但是他們的字段不一定是code、msg、data這樣的三個(gè)字段。例如你的結(jié)構(gòu)是error_code(code)、reason(msg)、result(data),那這樣就會(huì)導(dǎo)致解析失敗。而又不想因?yàn)閹讉€(gè)字段的數(shù)據(jù)結(jié)構(gòu)不一樣,所有的解析和業(yè)務(wù)邏輯重新寫一遍。而本庫就想讓你通過簡(jiǎn)單的改造,快速的接入,滿足你的數(shù)據(jù)結(jié)構(gòu)解析,所以提出了自定義數(shù)據(jù)結(jié)構(gòu)的概念。
注:如果服務(wù)器人員在寫接口時(shí)比較隨意完全沒有規(guī)范或者沒有code、msg這樣的結(jié)構(gòu),直接就是個(gè)bean,本庫就不支持后期可以考慮支持,暫時(shí)沒有提供針對(duì)非ApiResult結(jié)構(gòu)的支持
自定義ApiResult原理
ApiResult類中包含code、msg、data的get和set方法,以覆蓋重寫的方式來解決,在自定義之前需要先用自己的數(shù)據(jù)結(jié)構(gòu)對(duì)比庫中默認(rèn)的數(shù)據(jù)結(jié)構(gòu),一樣的不用重復(fù)添加或者覆寫。最主要的是覆寫getCode()、getMsg()、getData()、isOk()四個(gè)方法,但不是這四個(gè)方法都必須全部覆寫看看不一致的地方,哪些不一致就覆寫哪些,set相關(guān)方法不用覆寫。主要解決思想就是把不一致的數(shù)據(jù)結(jié)構(gòu),改造成和庫中默認(rèn)的結(jié)構(gòu)一致或者靠攏。
注意:自定義ApiResult類時(shí)
TestApiResult<T> extends ApiResult<T>其中<T>必須寫
舉列1:服務(wù)器返回的結(jié)構(gòu)是和默認(rèn)的標(biāo)準(zhǔn)結(jié)構(gòu)一模一樣,只是code碼為1表示成功,而庫中0表示成功。那么只需要覆寫isOk()
public class TestApiResult<T> extends ApiResult<T> {
@Override
public boolean isOk() {
return getCode()==1;//code等于1表示成功,所有覆寫isOk()
}
}
舉列2:服務(wù)器返回的結(jié)構(gòu)是error_code、reason、result和默認(rèn)的標(biāo)準(zhǔn)結(jié)構(gòu)完全不一樣
public class TestApiResult<T> extends ApiResult<T> {
int error_code; //對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)ApiResult的code
String reason;//對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)ApiResult的msg
T result;//對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)ApiResult的data
@Override
public T getData() {//因?yàn)閹炖锸褂胐ata字段,而你的結(jié)構(gòu)是result,所以覆寫getData()方法,setData()方法不用覆寫
return result;
}
@Override
public String getMsg() {//因?yàn)閹炖锸褂胢sg字段,而你的結(jié)構(gòu)是reason,所以覆寫getMsg()方法,setMsg()方法不用覆寫
return reason;
}
@Override
public int getCode() {//因?yàn)閹炖锸褂胏ode字段,而你的結(jié)構(gòu)是error_code,所以覆寫getCode()方法,setCode()方法不用覆寫
return error_code;
}
@Override
public boolean isOk() {//因?yàn)閹炖锸褂胏ode字段,code==0表示成功,但是你的數(shù)據(jù)結(jié)構(gòu)是error_code==0,所以覆寫isOk(),用error_code==0做為判斷成功的條件
return error_code == 0;//表示成功
}
}
舉列3:服務(wù)器返回的結(jié)構(gòu)是no,msg,obj結(jié)構(gòu),其中msg是一樣的就不用再特殊處理,no、obj不一樣需要處理
注:其它更多情景自己舉一反三
自定義ApiResult請(qǐng)求網(wǎng)絡(luò)步驟
假如你的請(qǐng)求鏈接是:
http://japi.juhe.cn/joke/content/list.from?key=f5236a9fb8fc75fac0a4d9b8c27a4e90&page=1&pagesize=10&sort=asc&time=1418745237
第一步:分析數(shù)據(jù)結(jié)構(gòu)
如果返回的字符串不好查看結(jié)構(gòu),可以使用工具分析,例如json格式化工具sojson、bejson、Chrome瀏覽器插件JSON-Handle、Json Viewer等
鏈接返回的json數(shù)據(jù):
第二步:自定義數(shù)據(jù)結(jié)構(gòu)
看到上面返回的json格式,結(jié)合自定義ApiResult原理,定義結(jié)構(gòu)如下:
public class TestApiResult<T> extends ApiResult<T> {
int error_code; //對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)ApiResult的code
String reason;//對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)ApiResult的msg
T result;//對(duì)應(yīng)默認(rèn)標(biāo)準(zhǔn)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>屬于公共的,同樣的數(shù)據(jù)結(jié)構(gòu)都可以使用到
第三步:準(zhǔn)備數(shù)據(jù)解析的result
自定義數(shù)據(jù)結(jié)構(gòu)TestApiResult是個(gè)通用的結(jié)構(gòu),實(shí)體的data是result,result是泛型T,具體表示什么,需要你自己查看返回json結(jié)構(gòu),本例中result字段中包含一個(gè)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 +
'}';
}
}
第四步:網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)
自定義的網(wǎng)絡(luò)請(qǐng)求必須用回調(diào)代理execute(CallBackProxy<? extends ApiResult<T>, T> proxy)來請(qǐng)求網(wǎng)絡(luò)
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());
}
}) {
});
注:通過以上四個(gè)步驟就完成了自定義數(shù)據(jù)結(jié)構(gòu)網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),是不是覺得寫法會(huì)有點(diǎn)長(zhǎng),CallBackProxy的泛型參數(shù)每次都需要填寫,其中TestApiResult是繼承ApiResult的,對(duì)于一個(gè)實(shí)際項(xiàng)目來講后臺(tái)的服務(wù)器數(shù)據(jù)結(jié)構(gòu)是固定的,也就是TestApiResult是固定的,這種方法太麻煩了,那有沒有簡(jiǎn)單的寫法,而又不破壞庫的使用方式,請(qǐng)看自定義ApiResult高級(jí)用法。
自定義ApiResult高級(jí)用法
上面已經(jīng)提到過使用自定義網(wǎng)絡(luò)請(qǐng)求必須要用new CallBackProxy<TestApiResult<Result>, Result>,會(huì)有很多重復(fù)的操作,結(jié)合上面我們看下如何簡(jiǎn)寫。講解之前先說下庫中實(shí)現(xiàn)方式,網(wǎng)絡(luò)請(qǐng)求EasyHttp.get()是返回一個(gè)GetRequest請(qǐng)求,EasyHttp.post()是返回一個(gè)PostRequest請(qǐng)求.如果想讓所有的請(qǐng)求execute()方法都自動(dòng)加上new CallBackProxy<TestApiResult<T>, T>,就需要修改execute()方法,而execute()方法是在GetRequest和PostRequest中,所以我們需要分別繼承GetRequest和PostRequest,重寫execute()方法。具體操作如下:
自定義GetRequest請(qǐng)求
注:下面代碼可以直接拷貝過去使用,其中的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) {
});
}
}
自定義PostRequest請(qǐng)求
注:下面代碼可以直接拷貝過去使用,其中的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) {
});
}
}
新建請(qǐng)求的管理類方便使用
public class HttpManager {
/**
* get請(qǐng)求
*/
public static GetRequest get(String url) {
return new CustomGetRequest(url);
}
/**
* post請(qǐng)求
*/
public static PostRequest post(String url) {
return new CustomPostRequest(url);
}
}
新的網(wǎng)絡(luò)請(qǐng)求方式
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) {//這么實(shí)現(xiàn)是不是沒有代理了
@Override
public void onError(ApiException e) {
super.onError(e);
showToast(e.getMessage());
}
@Override
public void onSuccess(Result result) {
if (result != null) showToast(result.toString());
}
});