【问题标题】:What is the best practice for parsing retrofit response on android with coroutines使用协程在 android 上解析改造响应的最佳实践是什么
【发布时间】:2021-02-26 20:40:57
【问题描述】:

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

我提供这样的改造单例:

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,并且最终也可能导致代码重复,谁能给我指出一个在最佳实践中实现的示例?

【问题讨论】:

  • 我可以就为什么这被否决获得一些反馈吗?
  • 我无法解释为什么这被否决了。但是,您的问题是关于 Retrofit 的,并且在代码示例中似乎与 Retrofit 没有太大关系。而且,由于 Retrofit 本身是一个外部库,因此您的“没有外部库”声明相当奇怪。无论如何,如果您的 minimal reproducible example 能够显示您如何配置 Retrofit、如何定义 Retrofit API 以及此代码示例与这些内容的关系,将会有所帮助。

标签: android kotlin retrofit kotlin-coroutines android-networking


【解决方案1】:

原则上,您可以创建一个 unwrapResponse() 泛型函数,该函数接受 Response&lt;T&gt; 并返回 Result&lt;T?&gt; 并结合您的算法。通过眼球,类似这样的东西:

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&lt;PopularShows&gt;

如果你真的想让unwrapResponse() 返回Result&lt;List&lt;Show&gt;?&gt;,你会得到类似的结果:

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&lt;List&lt;Show&gt;?&gt;

再一次,这完全靠眼球——这里可能需要调整。

【讨论】:

  • 是的,这基本上就是我想要的,我还在为仿制药苦苦挣扎,谢谢。
猜你喜欢
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
相关资源
最近更新 更多