Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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"

Here's the Dao Code:

@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)

}

The database bit:

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

And this is the function where I use it:

    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)
    }

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) 

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!!

like image 880
Kleckus Avatar asked Jan 06 '20 05:01

Kleckus


2 Answers

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.

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.

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.

like image 144
zsmb13 Avatar answered Nov 08 '22 08:11

zsmb13


Room Database doesn't want the user to perform an operation on main Thread.

You should use Background Thread to perform the Task.

You can use

.allowMainThreadQueries()

to skip the advised solution, but it is recommended to use Thread to perform Tasks.

Below are a few options.

1)

AsyncTask.execute(() -> //Write your db code here);

2)

 Thread {
       //Do your database´s operations here
       }.start()
like image 36
Vir Rajpurohit Avatar answered Nov 08 '22 08:11

Vir Rajpurohit