如何解决Android - ViewModel、LiveData、Room 和 Retrofit 以及协程放在 kotlin 中
我正在学习 Android,并且坚持让所有这些组件协同工作。我说的是 ViewModel、LiveData、Room、Retrofit 和协程。
所以,我想要实现的是:
当应用程序启动时,我想检查用户是否登录。如果没有登录,我什么都不做,如果他登录了,我会在主要活动中记录他的名字。用户可以通过另一个 api 调用进行身份验证。然后,当用户更新时,主要活动应将更改反映给用户。 我在 https://developer.android.com/jetpack/guide 部分遵循了谷歌代码实验室,但它不完整,我迷失在其中。
以下是代码块:
UserDao.kt
使用 Room DAO 的数据库查询
@Dao
interface UserDao {
@Query("SELECT * FROM user WHERE id = :userId")
fun get(userId: Long): LiveData<UserEntity?>
@Insert(onConflict = REPLACE)
suspend fun insert(userEntity: UserEntity)
@Query("SELECT COUNT(*) FROM user WHERE last_update >= :timeout")
suspend fun hasUser(timeout: Long): Boolean
}
UserService.kt
这是一个使用 Retrofit 的简单 api 调用
interface UserService {
@GET("users/current-user")
suspend fun getUser(): Response<User>
}
UserRepository.kt
main Activity 应该在加载时调用 get 并刷新用户(调用 api 并检索用户 ID),将用户 ID 保存在 savedStateHandler 中,并从刚刚保存的数据库中检索用户。但是在第一次启动时,savedStateHandler 是空的。当我从 api 获取用户时,我将其存储在数据库中,但传递给 userId
的 userDao.get(userId)
变量仍然为空,因此没有从数据库加载任何内容。我应该何时何地在savedStateHandler中保存用户的id?我在存储库中没有参考它。
此外,当应用程序启动时,不会触发调用。如何从活动中触发它?
不确定在可变实时数据变量中的何处设置用户以触发活动中的观察者。
suspend fun insert(userEntity: UserEntity) {
userDao.insert(userEntity)
}
suspend fun get(userId: Long): LiveData<UserEntity?> {
refreshUser()
return userDao.get(userId)
}
private suspend fun refreshUser() = withContext(Dispatchers.IO) {
launch {
// Check if user data was fetched recently.
val userExists = userDao.hasUser(FRESH_TIMEOUT)
if (!userExists) {
// Refreshes the data.
val response = userService.getUser()
try {
if (response.isSuccessful) {
Log.i("user","Success ${response.code()} - ${response.message()}")
// Updates the database. The LiveData object automatically
// refreshes,so we don't need to do anything else here.
val body: User? = response.body()
val user = UserEntity(
body!!.id,body.email,body.name.firstName,body.name.lastName,body.telephone,body.dateOfBirth,System.currentTimeMillis() / 1000
)
userDao.insert(user)
} else {
Log.w(
"user","Not successful ${response.code()} - ${response.message()}"
)
}
} catch (e: HttpException) {
Log.e("user","Exception ${response.code()} - ${response.message()}")
}
}
}
}
UserViewModel.kt
class UserViewModel @ViewModelInject constructor(
private val repository: UserRepository,@Assisted private val savedStateHandle: SavedStateHandle) : ViewModel() {
fun insert(userEntity: UserEntity) = viewModelScope.launch {
repository.insert(userEntity)
}
private val userId: Long? = savedStateHandle["uid"]
val user: LiveData<UserEntity?>
get() = liveData { repository.get(userId) }
}
MainActivity.kt
viewModel.user.observe(this) { user ->
Log.i("USER IS LOGGED",user.toString())
Toast.makeText(this,"HELLO ${user?.email}!!",Toast.LENGTH_SHORT).show()
}
解决方法
private val userId: Long? = savedStateHandle["uid"]
val user: LiveData<UserEntity?>
get() = liveData { repository.get(userId) }
应该
private val userId: MutableLiveData<Long> = savedStateHandle.getLiveData("uid")
val user: LiveData<UserEntity?>
get() = userId.switchMap { userId -> liveData { repository.get(userId) } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。