【发布时间】:2020-01-26 21:41:13
【问题描述】:
所以,我正在重写我的应用程序代码 te 是“干净的”(分层,遵循 Android 团队推荐的 MVVM 模式)
这里我有一个简单的 Retrofit 接口来与我的 API 通信
interface Api {
@GET("comments")
suspend fun getPlaceComments(@Query("placeId") placeId: String): Response<List<CommentResponse>>
@POST("comments")
suspend fun addPlaceComment(@Header("placeId") placeId: String, @Header("text") text: String): Response<Unit>
@DELETE("comments")
suspend fun deletePlaceComment(@Header("placeId") placeId: String): Response<Unit>
}
只是一个简单的 CRUD。
现在,上一层,我有我的 SocialRepository。为了避免代码重复,我创建了泛型方法callSafely,它接受一个挂起的 API 函数和一个 placeId 作为其参数。
class SocialRepository {
private val client: Api = ApiClient.webservice
private suspend fun <T> callSafely(
apiMethod: suspend (placeId: String) -> Response<T>,
placeId: String,
): T? {
Log.d(TAG, "$apiMethod called safely")
var response: Response<T>? = null
try {
response = apiMethod(placeId)
} catch (e: Exception) {
e.printStackTrace()
}
if (response?.isSuccessful != true) {
Log.w(TAG, "response.isSuccessful isn't true.")
}
return response?.body()
}
suspend fun getPlaceComments(placeId: String): List<CommentResponse>? {
return callSafely(client::getPlaceComments, placeId)
}
suspend fun deletePlaceComment(placeId: String): Unit? {
return callSafely(client::deletePlaceComment, placeId)
}
suspend fun addPlaceComment(placeId: String, text: String): Unit? {
return callSafely(client::addPlaceComment, placeId, text) // HERE LIES THE PROBLEM
// I can't pass additional data because the method signature won't match with what's defined in callSafely()
}
}
现在,它工作得很好,当然我也有我的 Activity 及其 ViewModel 和 ViewModel 调用存储库中的方法等。没关系。
重要的是添加地点评论需要额外的数据,例如评论的实际文本。获取和删除cmets只需要placeId,而添加评论时,它的内容,它的text也是必需的。
我读过在 Kotlin 中传递 vararg 函数是不可能的。我也不希望使用 List of params 之类的东西来混淆所有 API 方法,因为大多数情况下它是空的,只会造成混乱。
我可以走简单的路,只需将callSafely 的代码复制到addPlaceComment 并更改它,但这不是我想要的。我知道如何解决问题,但我不知道该怎么做the clean way。将来我可能会添加更多需要额外数据的端点(placeId 除外),问题将再次出现。
在这种情况下你会怎么做? “正确的方式”怎么写?
我什至不知道如何正确地表达我在寻找什么,这就是为什么这篇文章如此漫无边际。对此提前表示抱歉。我真的希望你能帮助我。
【问题讨论】:
标签: android generics kotlin retrofit