使用协程解析 android 上的改造响应的最佳做法是什么

What is the best practice for parsing retrofit response on android with coroutines

我正在尝试找出处理改造响应的最佳实践。

我提供这样的改装单件:

val okHttpClient = OkHttpClient.Builder()
      .addInterceptor(AuthInterceptor())
      .addInterceptor(httpLoggingInterceptor)
      .build()

val retrofit = Retrofit.Builder()
      .client(okHttpClient)
      .baseUrl(BuildConfig.BASE_URL)
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(CoroutinesResponseCallAdapterFactory())
      .build()
    
val service = retrofit.create(ShowsService::class.java)

服务界面是这样的:

interface ShowsService {

    @GET("popular")
    suspend fun fetchPopularShows(): Response<PopularShows>
}

我从 API 获得了一个节目列表,并在存储库中像这样解析它:

override suspend fun getShows(): Result<List<Show>?> {
    val shows = service.fetchPopularShows()
    val body = shows.body()
    val errorBody = shows.errorBody()
    return when {
        body != null -> {
            Result.Success(body.shows)
        }
        errorBody != null -> {
            Result.Error(Exception(errorBody.string()))
        }
        else -> {
            Result.Error(Exception("Unknown error: ${shows.raw().message}"))
        }
    }
}

但是,这感觉非常非 Kotlin,并且最终可能会导致代码重复,任何人都可以指出一个以最佳实践实现的示例吗?

原则上,您可以创建一个 unwrapResponse() 通用函数,它接受一个 Response<T> 和 return 一个 Result<T?> 并合并您的算法。从眼球来看,是这样的:

suspend fun <T> unwrapResponse(response: Response<T>): Result<T> {
    val body = response.body()
    val errorBody = response.errorBody()

    return when {
        body != null -> {
            Result.Success(body)
        }
        errorBody != null -> {
            Result.Error(Exception(errorBody.string()))
        }
        else -> {
            Result.Error(Exception("Unknown error: ${response.raw().message}"))
        }
    }
}

然后您可以致电 unwrapResponse(service.fetchPopularShows()) 以获得 Result<PopularShows>

如果你真的想让 unwrapResponse() 到 return 一个 Result<List<Show>?>,你会得到类似这样的结果:

suspend fun <T, R> unwrapResponse(response: Response<T>, unpacker: (T) -> R?): Result<R?> {
    val body = response.body()
    val errorBody = response.errorBody()

    return when {
        body != null -> {
            Result.Success(unpacker(body))
        }
        errorBody != null -> {
            Result.Error(Exception(errorBody.string()))
        }
        else -> {
            Result.Error(Exception("Unknown error: ${response.raw().message}"))
        }
    }
}

unwrapResponse(service.fetchPopularShows()) { it.shows } 然后会给你 Result<List<Show>?>.

同样,这完全是靠眼球——这里可能需要进行调整。