我正在学习Android,我一直致力于让所有这些组件协同工作。我说的是ViewModel、LiveData、Room、改装和协同程序。
因此,我想实现以下目标:
当应用程序启动时,我想检查用户是否登录。如果没有登录,我什么也不做,如果他登录了,我将他的名字记录在主活动中。用户可以通过另一个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
}
用户服务。kt
这是一个使用改进的简单api调用
interface UserService {
@GET("users/current-user")
suspend fun getUser(): Response<User>
}
用户存储库。kt
主活动应该调用get on load并刷新用户(调用api并检索用户id),将用户id保存在保存的StateHandler中,并从刚刚保存的数据库中检索用户。但是在第一次启动时,保存的StateHandler是空的。当我从api中获取用户时,我会将其存储在数据库中,但是传递给userDao.get(userId)
的userId
变量仍然为空,因此不会从数据库中加载任何内容。我应该在何时何地将用户的id保存在保存的StateHandler中?我在存储库中没有它的引用。此外,当应用程序启动时,调用不会被触发。我如何从活动中触发它?不确定在可变活动数据变量中的哪里设置用户,以便触发活动中的观察者。
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) }
}
主要活动。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) } }
我想测试我的数据库层,我发现自己陷入了一种第22条军规的境地。 测试用例由两件事组成: 保存一些实体 加载实体并断言数据库映射按预期工作 简而言之,问题在于: 是一种方法,这意味着它需要在 我的类是这样的: 测试用例是: 是的一个扩展函数,基本上是从上面的链接复制粘贴的 测试这个场景的正确方法是什么?在开发数据库映射层时,我需要这些类型的测试,以确保一切都如我所期望的那样工作。
对于LiveData和MVVM架构,我完全是个新手。我想知道如何观察一个实时数据 我通过以下方式从我的房间数据库中获取实时数据: 我希望ViewModel中的另一个变量,,在列表返回空(null)时进行更新。这将用于从Visible更新片段中的ImageView。去看电视了。看得见的 我如何检查如果是空的同步? 我四处阅读,看到一些人说使用,但是架构指南明确建议不要使用ViewModel中的任何观
我试图解决一个问题,但没有成功。每当数据库(数据库室)中特定模型的记录发生变化时,我想更新我的回收器视图。我使用ViewModel来处理模型数据,记录列表存储在LiveData中。 数据库 模型 刀 视图模型 碎片 现在,我的问题是为什么观察者只被调用一次(在片段的开始),然后没有被再次调用?我如何让观察者不断地倾听数据库中的变化(插入,更新,删除),以便我的回收器视图可以立即更新?非常感谢任何建
我读了文档,但在某些部分变得迷惑了。 ViewModel对象被设计为比views或LifeCycleOwners的特定实例化更长寿。这种设计还意味着您可以编写测试以更容易地覆盖ViewModel,因为它不知道视图和生命周期对象。ViewModel对象可以包含LifecycleObservers,如LiveData对象。但是,ViewModel对象绝不能观察到生命周期感知的可观察对象(如LiveDa
因此,我使用LiveData和ViewModel设置获取和插入数据的功能,并使用Room数据库保存数据。 将数据插入数据库后,我的RecyclerView不会更新数据。 RecyclerAdapterTransaksi.kt 使用RecyclerView显示数据库数据的片段 Pemasukkanframent。kt 使用LiveData的ViewModel类 TransaksiViewModel.
我正在努力把这个改型班翻译成科特林。它基本上是一个作为客户机工作的单例,我不确定我的Kotlin实现。UserAPI和ProfileAPI只是接口。 这是我的Kotlin实现。正如我所理解的,当类实例化时,init块将首先执行。 但有些事情告诉我,这不是正确的方法,或者可以做得更好。这里有什么我可以改进的吗? 更新!!! 可以吗?