使用协程解析 Android 上的改造响应的最佳实践是什么

Ziv*_*ten 1 android android-networking kotlin retrofit kotlin-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)
Run Code Online (Sandbox Code Playgroud)

服务接口是这样的:

interface ShowsService {

    @GET("popular")
    suspend fun fetchPopularShows(): Response<PopularShows>
}
Run Code Online (Sandbox Code Playgroud)

我从 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}"))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这感觉非常非 kotlin,并且最终可能会导致代码重复,任何人都可以向我指出一个以最佳实践实现此功能的示例吗?

Com*_*are 6

原则上,您可以创建一个unwrapResponse()通用函数,它接受 aResponse<T>并返回 aResult<T?>并合并您的算法。通过肉眼观察,是这样的:

\n
suspend fun <T> unwrapResponse(response: Response<T>): Result<T> {\n    val body = response.body()\n    val errorBody = response.errorBody()\n\n    return when {\n        body != null -> {\n            Result.Success(body)\n        }\n        errorBody != null -> {\n            Result.Error(Exception(errorBody.string()))\n        }\n        else -> {\n            Result.Error(Exception("Unknown error: ${response.raw().message}"))\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

如果你真的想允许unwrapResponse()返回 a Result<List<Show>?>,你最终会得到类似的结果:

\n
suspend fun <T, R> unwrapResponse(response: Response<T>, unpacker: (T) -> R?): Result<R?> {\n    val body = response.body()\n    val errorBody = response.errorBody()\n\n    return when {\n        body != null -> {\n            Result.Success(unpacker(body))\n        }\n        errorBody != null -> {\n            Result.Error(Exception(errorBody.string()))\n        }\n        else -> {\n            Result.Error(Exception("Unknown error: ${response.raw().message}"))\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

再说一次,这都是靠眼球 \xe2\x80\x94 这里可能需要调整。

\n