错误:无法访问主线程上的数据库,因为它可能长时间锁定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
问题描述
好的,因此,我正在尝试使用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固有异步的LiveData
,Flowable
或类似类型,在这种情况下,您可以从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屋!