Room LiveData vs AsyncTask用于不需要更新的单个查询

时间:2017-12-17 16:56:35

标签: android android-asynctask android-room android-livedata

我正在将我们的项目转换为使用Room ORM。当我需要更新LiveData对象时,它工作得很好,并且非常适用于AsyncTasks,例如插入,删除等,我不需要回调。但是当我需要一次需要回调的一次性查询时,我很困惑。选项是调用AsyncTask以使用DAO实现进行查询,或使用Observer调用LiveData,并在第一次接收后取消注册观察者。

3 个答案:

答案 0 :(得分:1)

我建议坚持使用LiveData,特别是如果您使用Room提供的ViewModel。在将所有Room,LiveData和ViewModel捆绑在一起时,ArchitectureComponents库确实做得很好,所以尽量坚持使用约定。

我建议坚持 LiveData ViewModels 的原因是

  1. ViewModels具有生命周期意识,这意味着它们会做出适当的响应 片段/活动状态的变化,否则将离开你的 AsyncTask要么检索死活动的数据,要么正在工作 当活动不再可能导致MemoryLeaks
  2. 最佳做法是(至少对于架构组件),以便View观察数据/对数据的更改。如果您只需要一个回调,请在收到数据后取消订阅。如果您当前正在使用RxJava
  3. ,请使用RxJava单个

    如果您觉得需要真正使用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