Android 網(wǎng)絡(luò)請(qǐng)求封裝總結(jié)
Android Http 網(wǎng)絡(luò)請(qǐng)求封裝,使用 Kotlin+Moshi+Coroutines+retrofit等封裝處理Http請(qǐng)求,支持多個(gè)域名多態(tài)數(shù)據(jù)返回。封裝要達(dá)到的目的特性就一個(gè):簡(jiǎn)潔的同步代碼風(fēng)格處理網(wǎng)絡(luò)異步請(qǐng)求!
GitHub 演示(NetWork分支):https://github.com/AnyLifeZLB/Android-Architecture/tree/NetWork
為什么要使用以下技術(shù)棧:
- 協(xié)程 Coroutines 而不是rxjava:rxjava 是個(gè)好東西但不是官方的,學(xué)習(xí)成本也高,后期官方推薦kotlin,引入?yún)f(xié)程簡(jiǎn)潔優(yōu)雅處理網(wǎng)絡(luò)請(qǐng)求
- Moshi 而不是Gson: Moshi 天生支持Kotlin空安全,使用CodeGen生成代碼比Gson反射注解效率高
- Retrofit 而不是直接OKHTTP :因?yàn)镽etrofit使用注解+動(dòng)態(tài)代理來優(yōu)雅的封裝調(diào)度OKHTTP去執(zhí)行
- 哪怕是使用自家的OkHttp,哪怕底層調(diào)用的始終是OkHttpClient,也需要依賴一個(gè)抽象的retrofit2.Call接口,依賴于抽象,而不是依賴于具體
- 同步的方式寫異步請(qǐng)求。簡(jiǎn)潔,簡(jiǎn)潔,目標(biāo)只有一個(gè):使用快捷方便簡(jiǎn)潔 !
封裝能達(dá)到的效果/目標(biāo)
- 多域名Host,多個(gè)環(huán)境,多態(tài)返回?cái)?shù)據(jù)處理
- 使用最新穩(wěn)定的技術(shù)方案實(shí)現(xiàn)快捷穩(wěn)定的請(qǐng)求交互
- 封裝各種Http異常處理,服務(wù)器返回的各種異常json 數(shù)據(jù)
1.關(guān)于 Retrofit
Retrofit的設(shè)計(jì)非常插件化而且輕量級(jí),接口設(shè)計(jì)真的是非常高內(nèi)聚而且低耦合,精妙的設(shè)計(jì)是極佳的研究素材。Retrofit底層請(qǐng)求 默認(rèn)由OKHTTP執(zhí)行,
Retrofit主要負(fù)責(zé)調(diào)度;其中 Retrofit中定義了4個(gè)接口:
-
Callback<T> 接口
這個(gè)接口就是retrofit請(qǐng)求數(shù)據(jù)返回的接口,只有兩個(gè)方法- void onResponse(Response<T> response);
- void onFailure(Throwable t);
Converter<F, T>
這個(gè)接口主要的作用就是將HTTP返回的數(shù)據(jù)解析成Java對(duì)象,主要有Xml、Gson、protobuf等等,你可以在創(chuàng)建Retrofit對(duì)象時(shí)添加你需要使用的Converter實(shí)現(xiàn)(看上面創(chuàng)建Retrofit對(duì)象的代碼)Call<T.>
這個(gè)接口主要的作用就是發(fā)送一個(gè)HTTP請(qǐng)求,Retrofit默認(rèn)的實(shí)現(xiàn)是OkHttpCall<T>,你可以根據(jù)實(shí)際情況實(shí)現(xiàn)你自己的Call類,這個(gè)設(shè)計(jì)和Volley的HttpStack接口設(shè)計(jì)的思想非常相似,子類可以實(shí)現(xiàn)基于HttpClient或HttpUrl Connection的HTTP請(qǐng)求工具,這種設(shè)計(jì)非常的插件化,而且靈活CallAdapter<R,T>
網(wǎng)絡(luò)請(qǐng)求執(zhí)行器(Call)的適配器CallAdapter用于對(duì)原始Call進(jìn)行再次封裝,如Call<R>到Observable<R>或者本SDK 中的HttpResult<T>
2.協(xié)程Coroutines
「協(xié)程 Coroutines」源自 Simula 和 Modula-2 語言,這個(gè)術(shù)語早在 1958 年就被 Melvin Edward Conway 發(fā)明并用于構(gòu)建匯編程序,說明協(xié)程是一種編程思想,并不局限于特定的語言; 協(xié)程設(shè)計(jì)的初衷是為了解決并發(fā)問題,讓 「協(xié)作式多任務(wù)」 實(shí)現(xiàn)起來更加方便。
在Android中使用協(xié)程的環(huán)境分為下面五種環(huán)境:
- 網(wǎng)絡(luò)請(qǐng)求
- 回調(diào)處理
- 數(shù)據(jù)庫操作
- 文件操作
- 其他耗時(shí)操作
3.數(shù)據(jù)返回封裝
| 字段 | 說明 |
|---|---|
| code | 業(yè)務(wù)返回狀態(tài)碼,注意業(yè)務(wù)狀態(tài)碼不要和標(biāo)準(zhǔn)Http狀態(tài)碼混淆 |
| message | 返回補(bǔ)充說明信息 |
| data[T] | 期待正常返回的業(yè)務(wù)數(shù)據(jù) |
假設(shè)公司各個(gè)業(yè)務(wù)服務(wù)器返回的Http Json數(shù)據(jù)格式都差不多三個(gè)大字段code[int] + msg[str] +data[T] ,名稱允許自定義不同
這里我們統(tǒng)一約定稱含有三個(gè)類似字段為包裝數(shù)據(jù)Http wrapper data定義為HttpWrapper.kt,每個(gè)Http請(qǐng)求正常都會(huì)含有這三個(gè)字段,
data字段很自然的我們會(huì)使用范型T來表示,這也是Http 請(qǐng)求回來實(shí)際參與業(yè)務(wù)處理的部分 .
- [code] 本字段表示業(yè)務(wù)服務(wù)是否獲取了期待的數(shù)據(jù),一般0或200 表示成功,其他值表示沒有獲取正常期望的業(yè)務(wù)數(shù)據(jù)如權(quán)限不足
另外,這個(gè)業(yè)務(wù)code 要和標(biāo)準(zhǔn)Http 請(qǐng)求響應(yīng)的編碼區(qū)分清除,標(biāo)準(zhǔn)Http 2xx 表示成功,4xx表示客戶端錯(cuò)誤,5xx 是服務(wù)器錯(cuò)誤
強(qiáng)烈建議業(yè)務(wù)code 的返回值不要和標(biāo)準(zhǔn)Http 請(qǐng)求響應(yīng)的編碼有重合避開[2xx,5xx]范圍 - [msg] msg 是對(duì)業(yè)務(wù)code的補(bǔ)充說明,可以簡(jiǎn)單的是OK 或者對(duì)應(yīng)的異常提示信息

如果你的App 請(qǐng)求的業(yè)務(wù)服務(wù)器返回json不包含類似這三字段結(jié)構(gòu)也沒關(guān)系:不是標(biāo)準(zhǔn)的HttpWrapper了,不需要實(shí)現(xiàn)HttpWrapper impl,相應(yīng)的判斷需要使用的時(shí)候進(jìn)行補(bǔ)齊。
//不是標(biāo)準(zhǔn)的HttpWrapper
viewModelScope.launch {
when (val result = EuropeanaApiService.getService().getEuropData()) {
is HttpResult.Success -> {
if(result.data.success){
Log.e("Success", MoshiUtils.toJson(result.data.items)) //多一層鏈路.item
}else{
Log.e("code is not ok","")
}
}
is HttpResult.Failure -> {
Log.e("Failure", result.message + " ----- " + result.code)
}
}
}
而有標(biāo)準(zhǔn)HttpWrapper 結(jié)構(gòu)就能寫法上更簡(jiǎn)潔,少了一層判斷和一層數(shù)據(jù)拆箱 result.data.items
//標(biāo)準(zhǔn)的HttpWrapper
viewModelScope.launch {
when (val result = ExceptionApiService.getService().status404()) {
is HttpResult.Success -> {
Log.e("Success", MoshiUtils.toJson(result.data))
}
is HttpResult.Failure -> {
Log.e("Failure", result.message + " ----- " + result.code)
}
}
}
在 HttpResponseCall<> 類中我們根據(jù)http 請(qǐng)求是否成功,4xx,5xx 分別對(duì)應(yīng)處理返回HttpResult<out T : Any>中的
- Success<T> 成功獲取期待的數(shù)據(jù)data范型T
- Failure(msg,code) 包含了業(yè)務(wù)錯(cuò)誤和Http 請(qǐng)求異常(timeout,networkerror)
更多請(qǐng)移步GitHub下載代碼查看,歡迎建議改進(jìn)。
4.Moshi 解析空安全處理,默認(rèn)值情況
這個(gè)情況非常多,大部分的閃退和異常源于數(shù)據(jù)的異常,比如某個(gè)必有字段沒有返回,導(dǎo)致異常
還有就是有些字段需要設(shè)置后端沒有返回的時(shí)候的默認(rèn)值
5.LiveData 還是Flow ?
為了簡(jiǎn)單演示,Demo 中使用的是LiveData,如果你的項(xiàng)目都用Kotlin 編寫了,建議遷移到Flow
從 LiveData 遷移到 Kotlin 數(shù)據(jù)流:https://juejin.cn/post/6979008878029570055
5.接入使用
參考文檔
Retrofit 2.0源碼分析 http://www.itdecent.cn/p/0c055ad46b6c
-
從架構(gòu)角度看Retrofit http://www.itdecent.cn/p/f57b7cdb1c99
感謝以下Api 提供方,祝你們長(zhǎng)青永存