Android 網(wǎng)絡(luò)請求封裝總結(jié)Moshi+Coroutines+Retrofit

Android 網(wǎng)絡(luò)請求封裝總結(jié)

Android Http 網(wǎng)絡(luò)請求封裝,使用 Kotlin+Moshi+Coroutines+retrofit等封裝處理Http請求,支持多個域名多態(tài)數(shù)據(jù)返回。封裝要達到的目的特性就一個:簡潔的同步代碼風格處理網(wǎng)絡(luò)異步請求!
GitHub 演示(NetWork分支):https://github.com/AnyLifeZLB/Android-Architecture/tree/NetWork

為什么要使用以下技術(shù)棧:

  • 協(xié)程 Coroutines 而不是rxjava:rxjava 是個好東西但不是官方的,學習成本也高,后期官方推薦kotlin,引入?yún)f(xié)程簡潔優(yōu)雅處理網(wǎng)絡(luò)請求
  • Moshi 而不是Gson: Moshi 天生支持Kotlin空安全,使用CodeGen生成代碼比Gson反射注解效率高
  • Retrofit 而不是直接OKHTTP :因為Retrofit使用注解+動態(tài)代理來優(yōu)雅的封裝調(diào)度OKHTTP去執(zhí)行
  • 哪怕是使用自家的OkHttp,哪怕底層調(diào)用的始終是OkHttpClient,也需要依賴一個抽象的retrofit2.Call接口,依賴于抽象,而不是依賴于具體
  • 同步的方式寫異步請求。簡潔,簡潔,目標只有一個:使用快捷方便簡潔 !

封裝能達到的效果/目標

    1. 多域名Host,多個環(huán)境,多態(tài)返回數(shù)據(jù)處理
    1. 使用最新穩(wěn)定的技術(shù)方案實現(xiàn)快捷穩(wěn)定的請求交互
    1. 封裝各種Http異常處理,服務(wù)器返回的各種異常json 數(shù)據(jù)

1.關(guān)于 Retrofit

Retrofit的設(shè)計非常插件化而且輕量級,接口設(shè)計真的是非常高內(nèi)聚而且低耦合,精妙的設(shè)計是極佳的研究素材。Retrofit底層請求 默認由OKHTTP執(zhí)行,
Retrofit主要負責調(diào)度;其中 Retrofit中定義了4個接口:

  • Callback<T> 接口
    這個接口就是retrofit請求數(shù)據(jù)返回的接口,只有兩個方法

    • void onResponse(Response<T> response);
    • void onFailure(Throwable t);
  • Converter<F, T>
    這個接口主要的作用就是將HTTP返回的數(shù)據(jù)解析成Java對象,主要有Xml、Gson、protobuf等等,你可以在創(chuàng)建Retrofit對象時添加你需要使用的Converter實現(xiàn)(看上面創(chuàng)建Retrofit對象的代碼)

  • Call<T.>
    這個接口主要的作用就是發(fā)送一個HTTP請求,Retrofit默認的實現(xiàn)是OkHttpCall<T>,你可以根據(jù)實際情況實現(xiàn)你自己的Call類,這個設(shè)計和Volley的HttpStack接口設(shè)計的思想非常相似,子類可以實現(xiàn)基于HttpClient或HttpUrl Connection的HTTP請求工具,這種設(shè)計非常的插件化,而且靈活

  • CallAdapter<R,T>
    網(wǎng)絡(luò)請求執(zhí)行器(Call)的適配器CallAdapter用于對原始Call進行再次封裝,如Call<R>到Observable<R>或者本SDK 中的HttpResult<T>

2.協(xié)程Coroutines

「協(xié)程 Coroutines」源自 Simula 和 Modula-2 語言,這個術(shù)語早在 1958 年就被 Melvin Edward Conway 發(fā)明并用于構(gòu)建匯編程序,說明協(xié)程是一種編程思想,并不局限于特定的語言; 協(xié)程設(shè)計的初衷是為了解決并發(fā)問題,讓 「協(xié)作式多任務(wù)」 實現(xiàn)起來更加方便。

在Android中使用協(xié)程的環(huán)境分為下面五種環(huán)境:

  • 網(wǎng)絡(luò)請求
  • 回調(diào)處理
  • 數(shù)據(jù)庫操作
  • 文件操作
  • 其他耗時操作

3.數(shù)據(jù)返回封裝

字段 說明
code 業(yè)務(wù)返回狀態(tài)碼,注意業(yè)務(wù)狀態(tài)碼不要和標準Http狀態(tài)碼混淆
message 返回補充說明信息
data[T] 期待正常返回的業(yè)務(wù)數(shù)據(jù)

假設(shè)公司各個業(yè)務(wù)服務(wù)器返回的Http Json數(shù)據(jù)格式都差不多三個大字段code[int] + msg[str] +data[T] ,名稱允許自定義不同
這里我們統(tǒng)一約定稱含有三個類似字段為包裝數(shù)據(jù)Http wrapper data定義為HttpWrapper.kt,每個Http請求正常都會含有這三個字段,
data字段很自然的我們會使用范型T來表示,這也是Http 請求回來實際參與業(yè)務(wù)處理的部分 .

  • [code] 本字段表示業(yè)務(wù)服務(wù)是否獲取了期待的數(shù)據(jù),一般0或200 表示成功,其他值表示沒有獲取正常期望的業(yè)務(wù)數(shù)據(jù)如權(quán)限不足
    另外,這個業(yè)務(wù)code 要和標準Http 請求響應的編碼區(qū)分清除,標準Http 2xx 表示成功,4xx表示客戶端錯誤,5xx 是服務(wù)器錯誤
    強烈建議業(yè)務(wù)code 的返回值不要和標準Http 請求響應的編碼有重合避開[2xx,5xx]范圍
  • [msg] msg 是對業(yè)務(wù)code的補充說明,可以簡單的是OK 或者對應的異常提示信息
image.png

如果你的App 請求的業(yè)務(wù)服務(wù)器返回json不包含類似這三字段結(jié)構(gòu)也沒關(guān)系:不是標準的HttpWrapper了,不需要實現(xiàn)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 結(jié)構(gòu)就能寫法上更簡潔,少了一層判斷和一層數(shù)據(jù)拆箱 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<> 類中我們根據(jù)http 請求是否成功,4xx,5xx 分別對應處理返回HttpResult<out T : Any>中的

  • Success<T> 成功獲取期待的數(shù)據(jù)data范型T
  • Failure(msg,code) 包含了業(yè)務(wù)錯誤和Http 請求異常(timeout,networkerror)

更多請移步GitHub下載代碼查看,歡迎建議改進。

4.Moshi 解析空安全處理,默認值情況

這個情況非常多,大部分的閃退和異常源于數(shù)據(jù)的異常,比如某個必有字段沒有返回,導致異常
還有就是有些字段需要設(shè)置后端沒有返回的時候的默認值

5.LiveData 還是Flow ?

為了簡單演示,Demo 中使用的是LiveData,如果你的項目都用Kotlin 編寫了,建議遷移到Flow
從 LiveData 遷移到 Kotlin 數(shù)據(jù)流:https://juejin.cn/post/6979008878029570055

5.接入使用

參考文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容