Ошибка: невозможно получить доступ к базе данных в главном потоке, поскольку он может заблокировать пользовательский интерфейс на длительный период времени. - Android Номер с использованием Kotlin - PullRequest
0 голосов
/ 06 января 2020

Итак, я пытаюсь использовать Android Комната для создания этой базы данных для этого проекта.

Прежде всего, это то, что у меня есть в моем файле Gradle относительно проблемы:

//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
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:

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) 

Это должно быть главой проблемы: Невозможно получить доступ к базе данных в главном потоке, поскольку она может потенциально заблокировать пользовательский интерфейс на длительный период времени. .

Что мне здесь не хватает? Заранее спасибо !!

Ответы [ 2 ]

1 голос
/ 06 января 2020

Room не позволяет использовать его из потока пользовательского интерфейса, поскольку запросы к базе данных будут обращаться к диску, что может занять много времени, а блокировка потока пользовательского интерфейса на этот период приведет к зависанию пользовательского интерфейса. От вас ожидают, что вы будете вызывать Room из фоновой ветки, и как вы туда доберетесь, зависит от вас. У вас есть выбор Java потоковых примитивов, Executors, Rx Java, сопрограмм и т. Д. c, в зависимости от того, с чем вы знакомы.

Технически вы можете обойти это ограничение Room, используя allowMainThreadQueries, но вы не должны никогда делать это в реальном приложении по причинам, изложенным выше. Этот переключатель присутствует только для тестирования.

Вы также можете посмотреть возвращение LiveData, Flowable или аналогичного типа, который по своей природе асинхронен с Room, так как в этих случаях вам разрешено вызывать Room методы из потока пользовательского интерфейса.

Подробнее см. в документации Room .

0 голосов
/ 06 января 2020

Room Database не хочет, чтобы пользователь выполнял операцию с основным потоком.

Вы должны использовать Фоновый поток для выполнения Задачи.

Вы можете использовать

.allowMainThreadQueries()

, чтобы пропустить рекомендованное решение, но рекомендуется использовать Thread для выполнения задач.

Ниже приведены несколько вариантов.

1)

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

2)

 Thread {
       //Do your database´s operations here
       }.start()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...