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!!
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.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With