深入RxEasyHttp網絡庫教你3分鍾學會自定義數據結構


github源碼地址:https://github.com/zhou-you/RxEasyHttp

RxEasyHttp庫默認ApiResult簡介

在自定義ApiResult之前,先了解本庫中默認提供的ApiResult方式,包含code、msg、data三個字段,其中默認code為0表示解析成功,內部是用ApiResult進行數據解析的。
默認ApiResult如下:

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數據:

code:服務器返回的狀態碼
msg:服務器返回的成功/失敗信息
data:返回的真實數據,也是上層在頁面需要展示的信息
isOk():請求成功的判斷方法,例如指定了code==0是成功才會回調onSuccess(T t),那么code的其它數值都會走失敗onError(ApiException e)

為什么需要自定義ApiResult

每個公司后台都有自己的一套數據結構規范,數據規范基本都會包含code碼,錯誤信息、返回的數據data。但是他們的字段不一定是code、msg、data這樣的三個字段。例如你的結構是error_code(code)、reason(msg)、result(data),那這樣就會導致解析失敗。而又不想因為幾個字段的數據結構不一樣,所有的解析和業務邏輯重新寫一遍。而本庫就想讓你通過簡單的改造,快速的接入,滿足你的數據結構解析,所以提出了自定義數據結構的概念。

注:如果服務器人員在寫接口時比較隨意完全沒有規范或者沒有code、msg這樣的結構,直接就是個bean,本庫就不支持后期可以考慮支持,暫時沒有提供針對非ApiResult結構的支持

自定義ApiResult原理

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不一樣需要處理

注:其它更多情景自己舉一反三

自定義ApiResult請求網絡步驟

假如你的請求鏈接是:
http://japi.juhe.cn/joke/content/list.from?key=f5236a9fb8fc75fac0a4d9b8c27a4e90&page=1&pagesize=10&sort=asc&time=1418745237

第一步:分析數據結構

如果返回的字符串不好查看結構,可以使用工具分析,例如json格式化工具sojsonbejson、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>屬於公共的,同樣的數據結構都可以使用到

第三步:准備數據解析的result

自定義數據結構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高級用法。

自定義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()方法。具體操作如下:

自定義GetRequest請求

注:下面代碼可以直接拷貝過去使用,其中的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請求

注:下面代碼可以直接拷貝過去使用,其中的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());
                    }
                });

使用方式對比

具體源碼請查看GitHub中提供的Demo:https://github.com/zhou-you/RxEasyHttp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM