【问题标题】:Room Database Query from background Thread来自后台线程的房间数据库查询
【发布时间】:2018-05-03 13:40:00
【问题描述】:

我读过在房间数据库中查询数据的一种方法是使用 Livedata,它可以在主线程上使用,因为它是异步的。

我想使用 LiveData 而不是 RxJava 或 AsyncTask。

为此,在我的存储库类中,我有函数 getSomeData() 返回 LiveData>,我在 viewModel 构造函数中调用此函数:

private var mObservableSomeData: LiveData<List<SomeData>>

init {
    mObservableSomeData = repository.getSomeData()
}

fun getSomeData(): LiveData<List<SomeData>> {
    return mObservableSomeData
}

但是它崩溃说:

无法访问主线程上的数据库,因为它可能会长时间锁定 UI。

我该怎么办?

【问题讨论】:

  • 在您的 Dao 类中,您是否也将查询的返回类型包装在 LiveData 中?
  • 这就是我所做的:@Query("SELECT * FROM somedata") fun loadAllData(): LiveData>
  • 错误到底指向哪一行?你也有插入查询吗?
  • 是的,我也有插入,是的,你可能是对的,是插入导致崩溃
  • 是的,使用像 codelab 这样的 AsyncTask,不过它是在 Java 中的 :)

标签: android observable android-room android-architecture-components android-livedata


【解决方案1】:

正如@LieForBananas 所指出的,您很可能在插入时遇到错误。每当你有 @Query 并且你将返回的数据包装到一个 observable 中时,例如LiveData 或 Flowable,您的查询默认在后台线程上执行。

请记住,房间数据库确保返回 observable 的查询在后台线程上运行。这就是为什么如果你在 Flowable 中包装返回值,你不必在创建观察者时显式编写 .subscribeOn(Schedulers.io)。而如果您使用 Flowable 进行网络调用(Single 可能会更好,因为通常我们只需要发出一次),那么您必须显式编写 .subscribeOn(Scheduler.io()) 以在后台线程上运行调用。

【讨论】:

    【解决方案2】:

    Room 不允许在主线程上进行数据库操作,除非您使用 allowMainThreadQueries() 允许在主线程上进行数据库操作。

    MyApp.database = Room.databaseBuilder(this,AppDatabase::class.java,"MyDatabase")
                         .allowMainThreadQueries()
                         .build()
    

    【讨论】:

    • 不,如果您将返回类型包装在LiveData 中,则无需设置.allowMainThreadQueries(),查询将在后台线程上异步运行LiveData
    • 这就是我所做的:@Query("SELECT * FROM somedata") fun loadAllData(): LiveData>
    • @LieForBananas,我同意“异步”,但我不确定“在后台线程上”。您能否向我们提供有关“在后台线程上”的文档或源代码?
    • @Bananadroid 当然,没问题,这里是来自documentation 的一小段引述:Room 会在数据库更新时生成更新 LiveData 对象所需的所有代码。生成的代码在需要时在后台线程上异步运行查询。
    • @LieForBananas 没关系。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多