0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

flowをラップして良い感じにレスポンスをハンドリングする

Posted at

昔参考にさせていただいたflowのラッパーメソッド(apiFlow)で、エラーコードとエラー時のbodyを取得できるようにした。
ちなみに、このラッパーを採用した理由は元記事に書かれている通りで、UIレイヤに例外をそのまま伝搬させたくなかったから。

apiFlow.kt
inline fun <reified T : Any> apiFlow(crossinline call: suspend () -> Response<T>): Flow<Result<T>> =
    flow<Result<T>> {
        try {
            val response = call()
            if (response.isSuccessful) {
                emit(Result.Success(value = response.body()!!))
            } else {
                val errorResponse = response.errorBody()?.let { errorBody ->
                    Gson().fromJson(errorBody.string(), ErrorResponse::class.java)
                }
                emit(Result.Error(errorCode = response.code(), errorResponse = errorResponse))
            }
        } catch (e: Exception) {
            // 例外発生時は強制的に400エラーとする
            emit(Result.Error(errorCode = 400, errorResponse = null))
        }
    }.onStart {
        emit(Result.Proceeding)
    }.flowOn(Dispatchers.IO)

Result.kt
sealed class Result<out T> {
    // APIコールが実行中である
    object Proceeding : Result<Nothing>()
    // APIコールが成功した
    data class Success<out T>(val value: T) : Result<T>()
    // APIコールが失敗した
    data class Error(val errorCode: Int?, val errorResponse: ErrorResponse?, val throwable: Throwable? = null) : Result<Nothing>()
}

ErrorResponseクラスは以下。
今回ErrorBodyの中身がjsonなのでパースしてる。

ErrorResponse.kt
data class ErrorResponse(
    @SerializedName("messageId") val messageId: String?,
    @SerializedName("errorMessage") val errorMessage: String?
) 

レスポンスを取得する側、ViewModelの処理はこんな感じ

SomeViewModel.kt
someRepository.getSomething().collectLatest { result ->
    when (result) {
        is Result.Success -> {
        }
        is Result.Error -> {
            logd("エラーコード:" + result.errorCode)
            logd("エラーレスポンス:" + result.errorResponse)

            // エラーハンドリング
            when (result.errorCode) {
                400 -> {
                }
                404 -> {
                } //などなど
            }
        }
        else -> {} //読込中状態が入る、何もしない
    }
}

もうちょっと改良の余地がありそう。
GsonもMoshiに載せ替えたい。

参照: https://zenn.dev/chmod644/articles/fc304b7e2508de

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?