深入RxEasyHttp網(wǎng)絡(luò)庫(kù)教你3分鐘學(xué)會(huì)自定義數(shù)據(jù)結(jié)構(gòu)

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

RxEasyHttp庫(kù)默認(rèn)ApiResult簡(jiǎn)介

在自定義ApiResult之前岗仑,先了解本庫(kù)中默認(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ù)晨雳,也是上層在頁(yè)面需要展示的信息
    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ù)血久,也是上層在頁(yè)面需要展示的信息
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ù)邏輯重新寫(xiě)一遍背桐。而本庫(kù)就想讓你通過(guò)簡(jiǎn)單的改造优烧,快速的接入,滿(mǎn)足你的數(shù)據(jù)結(jié)構(gòu)解析链峭,所以提出了自定義數(shù)據(jù)結(jié)構(gòu)的概念畦娄。

注:如果服務(wù)器人員在寫(xiě)接口時(shí)比較隨意完全沒(méi)有規(guī)范或者沒(méi)有code、msg這樣的結(jié)構(gòu)弊仪,直接就是個(gè)bean熙卡,本庫(kù)就不支持后期可以考慮支持,暫時(shí)沒(méi)有提供針對(duì)非ApiResult結(jié)構(gòu)的支持

自定義ApiResult原理

ApiResult類(lèi)中包含code励饵、msg驳癌、data的get和set方法,以覆蓋重寫(xiě)的方式來(lái)解決役听,在自定義之前需要先用自己的數(shù)據(jù)結(jié)構(gòu)對(duì)比庫(kù)中默認(rèn)的數(shù)據(jù)結(jié)構(gòu)颓鲜,一樣的不用重復(fù)添加或者覆寫(xiě)。最主要的是覆寫(xiě)getCode()典予、getMsg()甜滨、getData()、isOk()四個(gè)方法熙参,但不是這四個(gè)方法都必須全部覆寫(xiě)看看不一致的地方艳吠,哪些不一致就覆寫(xiě)哪些,set相關(guān)方法不用覆寫(xiě)孽椰。主要解決思想就是把不一致的數(shù)據(jù)結(jié)構(gòu)昭娩,改造成和庫(kù)中默認(rèn)的結(jié)構(gòu)一致或者靠攏。

注意:自定義ApiResult類(lèi)時(shí)TestApiResult<T> extends ApiResult<T> 其中<T>必須寫(xiě)

舉列1:服務(wù)器返回的結(jié)構(gòu)是和默認(rèn)的標(biāo)準(zhǔn)結(jié)構(gòu)一模一樣黍匾,只是code碼為1表示成功栏渺,而庫(kù)中0表示成功。那么只需要覆寫(xiě)isOk()

public class TestApiResult<T> extends ApiResult<T> {
    @Override
    public boolean isOk() {
        return getCode()==1;//code等于1表示成功锐涯,所有覆寫(xiě)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)閹?kù)里使用data字段纹腌,而你的結(jié)構(gòu)是result,所以覆寫(xiě)getData()方法,setData()方法不用覆寫(xiě)
        return result;
    }

    @Override
    public String getMsg() {//因?yàn)閹?kù)里使用msg字段霎终,而你的結(jié)構(gòu)是reason,所以覆寫(xiě)getMsg()方法,setMsg()方法不用覆寫(xiě)
        return reason;
    }

    @Override
    public int getCode() {//因?yàn)閹?kù)里使用code字段升薯,而你的結(jié)構(gòu)是error_code,所以覆寫(xiě)getCode()方法莱褒,setCode()方法不用覆寫(xiě)
        return error_code;
    }

    @Override
    public boolean isOk() {//因?yàn)閹?kù)里使用code字段,code==0表示成功涎劈,但是你的數(shù)據(jù)結(jié)構(gòu)是error_code==0,所以覆寫(xiě)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格式化工具sojsonbejson扭吁、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)來(lái)請(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());
                    }
                }) {
                });

注:通過(guò)以上四個(gè)步驟就完成了自定義數(shù)據(jù)結(jié)構(gòu)網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù),是不是覺(jué)得寫(xiě)法會(huì)有點(diǎn)長(zhǎng)由蘑,CallBackProxy的泛型參數(shù)每次都需要填寫(xiě)闽寡,其中TestApiResult是繼承ApiResult的,對(duì)于一個(gè)實(shí)際項(xiàng)目來(lái)講后臺(tái)的服務(wù)器數(shù)據(jù)結(jié)構(gòu)是固定的尼酿,也就是TestApiResult是固定的爷狈,這種方法太麻煩了,那有沒(méi)有簡(jiǎn)單的寫(xiě)法裳擎,而又不破壞庫(kù)的使用方式涎永,請(qǐng)看自定義ApiResult高級(jí)用法。

自定義ApiResult高級(jí)用法

上面已經(jīng)提到過(guò)使用自定義網(wǎng)絡(luò)請(qǐng)求必須要用new CallBackProxy<TestApiResult<Result>, Result>鹿响,會(huì)有很多重復(fù)的操作羡微,結(jié)合上面我們看下如何簡(jiǎn)寫(xiě)。講解之前先說(shuō)下庫(kù)中實(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盯蝴,重寫(xiě)execute()方法。具體操作如下:

自定義GetRequest請(qǐng)求

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

注:下面代碼可以直接拷貝過(guò)去使用捧挺,其中的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)求的管理類(lèi)方便使用

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)是不是沒(méi)有代理了
                    @Override
                    public void onError(ApiException e) {
                        super.onError(e);
                        showToast(e.getMessage());
                    }

                    @Override
                    public void onSuccess(Result result) {
                        if (result != null) showToast(result.toString());
                    }
                });

使用方式對(duì)比

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尿瞭,隨后出現(xiàn)的幾起案子松忍,更是在濱河造成了極大的恐慌,老刑警劉巖筷厘,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸣峭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酥艳,警方通過(guò)查閱死者的電腦和手機(jī)摊溶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)充石,“玉大人莫换,你說(shuō)我怎么就攤上這事≈枇澹” “怎么了拉岁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)惰爬。 經(jīng)常有香客問(wèn)我喊暖,道長(zhǎng),這世上最難降的妖魔是什么撕瞧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任陵叽,我火速辦了婚禮,結(jié)果婚禮上丛版,老公的妹妹穿的比我還像新娘巩掺。我一直安慰自己,他們只是感情好页畦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布胖替。 她就那樣靜靜地躺著,像睡著了一般豫缨。 火紅的嫁衣襯著肌膚如雪独令。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天州胳,我揣著相機(jī)與錄音记焊,去河邊找鬼。 笑死栓撞,一個(gè)胖子當(dāng)著我的面吹牛遍膜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓤湘,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瓢颅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了弛说?” 一聲冷哼從身側(cè)響起挽懦,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎木人,沒(méi)想到半個(gè)月后信柿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體冀偶,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年渔嚷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了进鸠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡形病,死狀恐怖客年,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漠吻,我是刑警寧澤量瓜,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站途乃,受9級(jí)特大地震影響绍傲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜欺劳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一唧取、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧划提,春花似錦枫弟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至伊履,卻和暖如春韩容,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唐瀑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工群凶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哄辣。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓请梢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親力穗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子毅弧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容