由于RxJava2使用的JSON键命名约定,我正在努力在我的Kotlin应用程序中跨Retrofit、Room和API保持一致的类型。我试图研究解决以下问题的最好方法,但我想不出更好的方法来解决它,我对社区提供的东西很感兴趣。
考虑下面的例子;
我在Android上使用Kotlin语言,并使用Retrofit和GSON执行网络请求。根据响应是Array
还是单个Object
,我使用的API为JSON提供了不同的根密钥名。
每个Object
的有效负载是相同的,但如果响应是Array
,则根密钥是复数。
例如,假设我有一个为用户定义的数据类:
data class User(var id: Int?, name: String?)
如果我向单个用户发出API请求,该API将返回以下内容:
{
"user": {
"id": 1,
"name: "Sam"
}
}
如果我向多个用户发出API请求,该API将返回以下内容:
{
"users": [{
"id": 1,
"name: "Sam"
}]
}
有效负载是相同的,但根密钥在user
和users
之间变化。我已经创建了一个数据类来处理单独的根键:
data class Users(
@SerializedName("users") var users: List<User>?,
@SerializedName("user") var user: User?
)
当发出单独的API请求时,我对两者都使用Users
数据类:
/** GET single user by ID */
@GET("users/{id}")
fun getUser(
@Path("id") id: Int?): Single<Users>
/** GET list of users */
@GET("users")
fun getUsers(): Single<Users>
当我将响应保存到Room数据库时,我分别使用response.users
或response.user
访问它。设置房间以返回User
或List<User>
形式的查询,这在RxJava2流中使用Retrofit请求时会产生问题。例如,如果房间数据库返回Maybe<List<User>>
,则这是一个非常简单的流
usersRepository.getAll()
.switchIfEmpty(api.getUsers())
usersRepository.getAll()
的结果是List<User>
,但是如果来自数据库的结果是空的,并且我尝试回退到API请求,RxJava2将显示Incompatible Type
错误,因为api.getUsers()
请求返回类型Single<Users>
而不是Single<List<User>>
。如果API请求能够使用相同的类型,我就不会有问题,但是我不能在Retrofit请求上指定Single<List<User>>
,因为GSON不能正确地反序列化响应。
正因为如此,根据我目前对这个问题的理解(这可能是外行的,我很愿意被塑造),我正在分离数据库和API请求,并做了大量的empty
/null
检查,这阻止了我将所有东西都保存在一个漂亮而整洁的RxJava2流中。
我希望这个问题足够清楚,我重视每个人的意见。谢谢您抽时间见我!
发布于 2019-02-19 10:17:59
这是一个非常常见的问题,人们喜欢做的是创建一个包装器类来处理转换、验证和所有其他痛苦的工作,并使用该类来执行网络请求,而不是直接调用改进的api。
例如,考虑像这样创建一个类:
class UserClient {
private val userApi: UserApi
fun getUser(id: Int): Single<User> {
return userApi.getUser(id) // This has a type of Single<Users>
.map { it.user } // now it's map to Single<User>
}
fun getUsers(): Single<List<User>> {
return userApi.getUsers() // This has a type of Single<Users>
.doOnSuccess { Log.d(TAG, "yay!")}
.doOnError { e -> Log.d(TAG, "Something went wrong: $e")}
.map { it.users } // Now it's map to Single<List<User>>
}
}
然后你可以这样做:
usersRepository.getAll()
.switchIfEmpty(UserClient.getInstance().getUsers())
https://stackoverflow.com/questions/54735344
复制相似问题