错误:无法访问主线程上的数据库,因为它可能长时间锁定UI. -使用Kotlin的Android Room [英] Error: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. - Android Room using Kotlin

查看:133
本文介绍了错误:无法访问主线程上的数据库,因为它可能长时间锁定UI. -使用Kotlin的Android Room的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,因此,我正在尝试使用Android Room为该项目创建此数据库.

Okay, so, I am trying to use Android Room to create this database for this project.

首先,这是我在Gradle文件中关于此问题的内容:

First of all, this is what I have in my Gradle file regarding the issue:

//Room database
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0"

    implementation "androidx.room:room-runtime:2.2.3"
    kapt "androidx.room:room-compiler:2.2.3"
    implementation "androidx.room:room-ktx:2.2.3"

这是Dao代码:

@Dao
interface DebtsDao {

    @Query("SELECT * FROM debts")
    fun getDebtsList() : List<Debts>

    @Query("SELECT * FROM debts WHERE name LIKE :name")
    fun getNamedDebt(name : String) : Debts

    @Insert
    fun insertInDatabase(debt : Debts)

    @Delete
    fun deleteFromDatabase(debt : Debts)

}

数据库位:

@Database(entities = arrayOf(Debts::class), version = 1)
abstract class AppDatabase : RoomDatabase()
{
    abstract fun debtsDao() : DebtsDao
}

这是我使用它的功能:

    fun refreshRecyclerView()
    {
        val database = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "account").build()

        val list : List<Debts> = database.debtsDao().getDebtsList()

        recycler_view_debts.layoutManager = LinearLayoutManager(this)
        recycler_view_debts.adapter = RecAdapter(this, list)
    }

我尝试按照Android页面上的教程进行操作,但未按预期工作.我在Android Studio上遇到以下错误:

I tried following the tutorial on Android's page, but it didn't work as expected. I got the following error on Android Studio:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.project.watchingmoneyfly, PID: 17067
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.project.watchingmoneyfly/com.project.watchingmoneyfly.Activities.MainActivity}: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
     Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:267)
        at androidx.room.RoomDatabase.beginTransaction(RoomDatabase.java:351)
        at com.project.watchingmoneyfly.RoomDatabase.DebtsDao_Impl.insertInDatabase(DebtsDao_Impl.java:79)
        at com.project.watchingmoneyfly.Activities.MainActivity.onCreate(MainActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:6662)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6077) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 

这应该是问题的根源:无法访问主线程上的数据库,因为它可能长时间锁定UI.

This should be the head of the problem: Cannot access the database on the main thread since it may potentially lock the UI for a long period of time.

我在这里想念什么?在此先感谢!

What am I missing here? Thanks in advance!!

推荐答案

Room阻止您从UI线程使用它,因为数据库查询将访问磁盘,这可能需要很长时间,并且为此阻塞了UI线程持续时间将冻结用户界面.您应该从后台线程调用Room,而如何到达则取决于您自己.您可以根据自己的熟悉程度选择Java线程原语,Executor,RxJava,协程等.

Room prevents you from using it from the UI thread, because database queries will access the disk, which can take a long time, and blocking the UI thread for that duration will freeze the user interface. You're expected to call Room from a background thread instead, how you get there is up to you. You have a choice of Java threading primitives, Executors, RxJava, coroutines, etc, depending on what you're familiar with.

您可以使用 allowMainThreadQueries ,但是出于上面列出的原因,您应该从不在真实的应用程序中执行此操作.此开关仅用于测试.

You can technically circumvent this limitation of Room by using allowMainThreadQueries, but you should never do this in a real application, for the reasons layed out above. This switch is only present for testing.

您还可以考虑返回与Room固有异步的LiveDataFlowable或类似类型,在这种情况下,您可以从UI线程调用Room方法.

You can also look into returning a LiveData, Flowable, or similar type that's inherently asynchronous from Room, as in those cases, you're allowed to call Room methods from the UI thread.

有关更多信息,请参见房间文档.

See the Room documentation for more info.

这篇关于错误:无法访问主线程上的数据库,因为它可能长时间锁定UI. -使用Kotlin的Android Room的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆