Android 網絡請求封裝總結
Android Http 網絡請求封裝,使用 Kotlin+Moshi+Coroutines+retrofit等封裝處理Http請求,支持多個域名多態數據返回。封裝要達到的目的特性就一個:簡潔的同步代碼風格處理網絡異步請求!
GitHub 演示(NetWork分支):https://github.com/AnyLifeZLB/Android-Architecture/tree/NetWork
為什么要使用以下技術棧:
- 協程 Coroutines 而不是rxjava:rxjava 是個好東西但不是官方的,學習成本也高,后期官方推薦kotlin,引入協程簡潔優雅處理網絡請求
- Moshi 而不是Gson: Moshi 天生支持Kotlin空安全,使用CodeGen生成代碼比Gson反射注解效率高
- Retrofit 而不是直接OKHTTP :因為Retrofit使用注解+動態代理來優雅的封裝調度OKHTTP去執行
- 哪怕是使用自家的OkHttp,哪怕底層調用的始終是OkHttpClient,也需要依賴一個抽象的retrofit2.Call接口,依賴于抽象,而不是依賴于具體
- 同步的方式寫異步請求。簡潔,簡潔,目標只有一個:使用快捷方便簡潔 !
封裝能達到的效果/目標
- 多域名Host,多個環境,多態返回數據處理
- 使用最新穩定的技術方案實現快捷穩定的請求交互
- 封裝各種Http異常處理,服務器返回的各種異常json 數據
1.關于 Retrofit
Retrofit的設計非常插件化而且輕量級,接口設計真的是非常高內聚而且低耦合,精妙的設計是極佳的研究素材。Retrofit底層請求 默認由OKHTTP執行,
Retrofit主要負責調度;其中 Retrofit中定義了4個接口:
-
Callback<T> 接口
這個接口就是retrofit請求數據返回的接口,只有兩個方法- void onResponse(Response<T> response);
- void onFailure(Throwable t);
Converter<F, T>
這個接口主要的作用就是將HTTP返回的數據解析成Java對象,主要有Xml、Gson、protobuf等等,你可以在創建Retrofit對象時添加你需要使用的Converter實現(看上面創建Retrofit對象的代碼)Call<T.>
這個接口主要的作用就是發送一個HTTP請求,Retrofit默認的實現是OkHttpCall<T>,你可以根據實際情況實現你自己的Call類,這個設計和Volley的HttpStack接口設計的思想非常相似,子類可以實現基于HttpClient或HttpUrl Connection的HTTP請求工具,這種設計非常的插件化,而且靈活CallAdapter<R,T>
網絡請求執行器(Call)的適配器CallAdapter用于對原始Call進行再次封裝,如Call<R>到Observable<R>或者本SDK 中的HttpResult<T>
2.協程Coroutines
「協程 Coroutines」源自 Simula 和 Modula-2 語言,這個術語早在 1958 年就被 Melvin Edward Conway 發明并用于構建匯編程序,說明協程是一種編程思想,并不局限于特定的語言; 協程設計的初衷是為了解決并發問題,讓 「協作式多任務」 實現起來更加方便。
在Android中使用協程的環境分為下面五種環境:
- 網絡請求
- 回調處理
- 數據庫操作
- 文件操作
- 其他耗時操作
3.數據返回封裝
字段 | 說明 |
---|---|
code | 業務返回狀態碼,注意業務狀態碼不要和標準Http狀態碼混淆 |
message | 返回補充說明信息 |
data[T] | 期待正常返回的業務數據 |
假設公司各個業務服務器返回的Http Json數據格式都差不多三個大字段code[int] + msg[str] +data[T] ,名稱允許自定義不同
這里我們統一約定稱含有三個類似字段為包裝數據Http wrapper data定義為HttpWrapper.kt,每個Http請求正常都會含有這三個字段,
data字段很自然的我們會使用范型T來表示,這也是Http 請求回來實際參與業務處理的部分 .
- [code] 本字段表示業務服務是否獲取了期待的數據,一般0或200 表示成功,其他值表示沒有獲取正常期望的業務數據如權限不足
另外,這個業務code 要和標準Http 請求響應的編碼區分清除,標準Http 2xx 表示成功,4xx表示客戶端錯誤,5xx 是服務器錯誤
強烈建議業務code 的返回值不要和標準Http 請求響應的編碼有重合避開[2xx,5xx]范圍 - [msg] msg 是對業務code的補充說明,可以簡單的是OK 或者對應的異常提示信息
如果你的App 請求的業務服務器返回json不包含類似這三字段結構也沒關系:不是標準的HttpWrapper了,不需要實現HttpWrapper impl,相應的判斷需要使用的時候進行補齊。
//不是標準的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)
}
}
}
而有標準HttpWrapper 結構就能寫法上更簡潔,少了一層判斷和一層數據拆箱 result.data.items
//標準的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<> 類中我們根據http 請求是否成功,4xx,5xx 分別對應處理返回HttpResult<out T : Any>中的
- Success<T> 成功獲取期待的數據data范型T
- Failure(msg,code) 包含了業務錯誤和Http 請求異常(timeout,networkerror)
更多請移步GitHub下載代碼查看,歡迎建議改進。
4.Moshi 解析空安全處理,默認值情況
這個情況非常多,大部分的閃退和異常源于數據的異常,比如某個必有字段沒有返回,導致異常
還有就是有些字段需要設置后端沒有返回的時候的默認值
5.LiveData 還是Flow ?
為了簡單演示,Demo 中使用的是LiveData,如果你的項目都用Kotlin 編寫了,建議遷移到Flow
從 LiveData 遷移到 Kotlin 數據流:https://juejin.cn/post/6979008878029570055
5.接入使用
參考文檔
Retrofit 2.0源碼分析 http://www.lxweimin.com/p/0c055ad46b6c
-
從架構角度看Retrofit http://www.lxweimin.com/p/f57b7cdb1c99
感謝以下Api 提供方,祝你們長青永存