我正在将我们的项目转换为使用Room ORM。当我需要更新LiveData对象时,它工作得很好,并且非常适用于AsyncTasks,例如插入,删除等,我不需要回调。但是当我需要一次需要回调的一次性查询时,我很困惑。选项是调用AsyncTask以使用DAO实现进行查询,或使用Observer调用LiveData,并在第一次接收后取消注册观察者。
答案 0 :(得分:1)
我建议坚持使用LiveData,特别是如果您使用Room提供的ViewModel。在将所有Room,LiveData和ViewModel捆绑在一起时,ArchitectureComponents库确实做得很好,所以尽量坚持使用约定。
我建议坚持 LiveData 和 ViewModels 的原因是
如果您觉得需要真正使用AsyncTask,我建议您使用AsyncTaskLoader。这是一个更健壮/生命周期感知的后台线程操作,它将缓存您的数据(它非常类似于AsyncTask,所以实现细节不会太陌生),所以如果您旋转设备,数据将被缓存并立即可用,您不会有内存泄漏。另请查看Android小组对加载程序的Video。
但我建议使用带有ViewModels的LiveData。
答案 1 :(得分:0)
我在房间实施方面遇到了同样的问题。至于 LiveData 按房间返回,我们可以在主线程上观察而不在主线程上执行数据库操作。 但是为了在没有LiveData的情况下获取Raw对象,我们无法直接进行,因为不允许在主线程上进行数据库操作。
我已经使用LiveData列出了一些内容,我会在数据库更新后立即更新。但对于某些操作,我只需要获取一次并停止观察数据库,因为我知道它不会改变。
在我的情况下,我只用了一次 RxJava来观察查询结果
创建 Observable ,以便从存储库中获取用户ID
Observable.create(object : ObservableOnSubscribe<User> {
override fun subscribe(e: ObservableEmitter<User>) {
val user= userRepo.getUserById(currentUserId)
e.onNext(user)
e.onComplete()
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(GetCurrentUserByIdSubscriber())
<强>存储库强>
fun getUserById(id: Int): User= userDao.getUserById(id)
<强>道强>
@Query("SELECT * FROM users WHERE id= :id")
fun getUserById(id: Int): User
您可以看到我正在返回普通用户对象而不是LiveData。
在我希望观察此活动的活动中
private inner class GetCurrentUserByIdSubscriber : Observer<User> {
override fun onSubscribe(d: Disposable) {}
override fun onNext(t: User) {
// update the view after getting the data from database
user_name.text = t.name
}
override fun onComplete() {}
override fun onError(e: Throwable) {}
}
这就是我如何使用RxJava在IO线程上执行一次数据库获取,并在从数据库中获取对象后立即获取回调。 在获得结果后,您可以在订阅上从subscribe()方法返回取消订阅。
答案 2 :(得分:0)
转换方法distinctUntilChanged
中有一个简单的解决方案。仅在更改数据后才公开新数据。
万一事件行为使用此方法: https://stackoverflow.com/a/55212795/9381524