在自定義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()); } });