以前的文章 RxJava處理業務異常的幾種方式 曾經介紹過 Retrofit 的異常能夠有多種處理方式。react
其中,可使用 RxJava 的錯誤處理操做符,它們是專門用來處理異常的。bash
隨便例舉兩個操做符:網絡
onErrorReturn 操做符,表示當發生錯誤的時候,發射一個默認值而後結束數據流。因此 Subscriber 看不到異常信息,看到的是正常的數據流結束狀態。併發
onErrorResumeNext 操做符,表示當錯誤發生的時候,使用另一個數據流繼續發射數據。在返回的被觀察者中是看不到錯誤信息的。函數
此次我結合 Kotlin 擴展函數的特性來嘗試處理異常。post
網絡請求返回的 Response 大可能是採用以下這種形式:ui
{
"code":0,
"message":"success",
"data":{
...
}
}
複製代碼
對於客戶端開發而言,咱們會封裝一個基類的HttpResponse。this
data class HttpResponse<T>(
var code: Int = -1, //0: 成功 1: xxx錯誤或過時 2: 業務邏輯錯誤 500:系統內部錯誤 998表示Token無效
var message: String? = null,
var data: T? = null
) : UnProguard {
val isOkStatus: Boolean
get() = code == 0
}
複製代碼
其中,UnProguard是一個空的接口,主要是方便 App 在混淆的時候保留部分類。spa
interface UnProguard : Serializable
複製代碼
一般狀況下,咱們會在 Observer 的 onError 中按照以下的方式處理異常:code
viewModel.getHelps(this)
.subscribe({
if (it.isOkStatus) {
multi_status_view.showContent()
adapter.addData(it.data?.list)
} else {
multi_status_view.showError()
}
}, { multi_status_view.showError() })
複製代碼
若是咱們利用 RxJava 的錯誤處理操做符,能夠編寫以下的擴展函數:
import com.safframework.utils.RetryWithDelay
import io.reactivex.Maybe
/** * * @FileName: * cn.magicwindow.core.ext.`Maybe+Extension`.kt * @author: Tony Shen * @date: 2018-07-19 17:31 * @version V1.0 <描述當前版本功能> */
/** * 嘗試重試 * 默認有3次重試機會,每次的延遲時間是1000ms */
fun <T> Maybe<T>.retryWithDelayMillis(maxRetries: Int=3, retryDelayMillis: Int=1000): Maybe<T> =
this.retryWhen(RetryWithDelay(maxRetries,retryDelayMillis))
/** * 遇到錯誤時,可以提早捕獲異常,併發射一個默認的值。 * 後面無須再作異常處理 */
fun <T> Maybe<T>.errorReturn(defValue:T): Maybe<T> = this.onErrorReturn {
it -> it.printStackTrace()
return@onErrorReturn defValue
}
fun <T> Maybe<T>.errorReturn(defValue:T,action: (Throwable) -> Unit): Maybe<T> = this.onErrorReturn {
action.invoke(it)
return@onErrorReturn defValue
}
/** * 遇到錯誤時,可以提早捕獲異常,並返回一個新的Maybe * 後面無須再作異常處理 */
fun <T> Maybe<T>.errorResumeNext(defValue:T):Maybe<T> = this.onErrorResumeNext(Maybe.just(defValue))
fun <T> Maybe<T>.errorResumeNext():Maybe<T> = this.onErrorResumeNext(Maybe.empty())
複製代碼
擴展函數 errorReturn 的使用:
viewModel.getHelps(this)
.errorReturn(HttpResponse()) {
multi_status_view.showError()
}
.subscribe{
if (it.isOkStatus) {
multi_status_view.showContent()
adapter.addData(it.data?.list)
} else {
multi_status_view.showError()
}
}
複製代碼
這樣無須在 onError 中處理異常,並且 errorReturn 仍是一個高階函數。它的 action 參數傳遞的是一個函數,專門用於處理異常。每個網絡請求的異常處理並不會都同樣,能夠用該函數來傳遞不一樣的異常處理。
合理利用 Kotlin 的擴展函數,能夠編寫優雅的代碼。而使用高階函數,則能夠達到的進一步的抽象。
該系列的相關文章:
Java與Android技術棧:每週更新推送原創技術文章,歡迎掃描下方的公衆號二維碼並關注,期待與您的共同成長和進步。