getDatabase вызывается рекурсивно с использованием Room - PullRequest
0 голосов
/ 09 июня 2018

Я получаю сообщение об ошибке при попытке инициализировать базу данных.Я использую Android Room и хочу использовать RoomDatabaseBuilder для выполнения обратного вызова и заполнения своей базы данных.

Я выполняю метод getDatabase в своем классе Activity, но затем я использую dao для получения информации из базы данных, и приложение вылетает.Это мой первый контакт с Android Room, может быть, я забочусь о некоторых важных делах.Кто-нибудь может помочь мне с этим?

Класс базы данных:

static RoomDatabase.Callback rdc = new RoomDatabase.Callback() {

    @Override
    public void onOpen(@NonNull SupportSQLiteDatabase db) {
        super.onOpen(db);
        Log.d(TAG, "Debug: onOpen");

        //Borramos todos los sonidos de la base de datos
        INSTANCE.soundsDao().deleteAllSounds(); // Instance is "private static DatabaseSounds INSTANCE;"

Строка активности источника сбоя:

db = DatabaseSounds.getDatabase(getApplicationContext());
   AsyncTask task = new LoadGridAsyncTask().execute(); **

   private class LoadGridAsyncTask extends AsyncTask<Void, Void, Integer> {

        @Override
        protected Integer doInBackground(Void... voids) {
            //Extraemos el listado de sonidos y los convertimos a DTO
            List<EntitySounds> listSounds = db.soundsDao().getAll(); **** THIS is the line of crash

Это ошибка

java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:325)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:761)
     Caused by: java.lang.IllegalStateException: getDatabase called recursively
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:203)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
        at android.arch.persistence.room.RoomDatabase.compileStatement(RoomDatabase.java:244)
        at android.arch.persistence.room.SharedSQLiteStatement.createNewStatement(SharedSQLiteStatement.java:65)
        at android.arch.persistence.room.SharedSQLiteStatement.getStmt(SharedSQLiteStatement.java:72)
        at android.arch.persistence.room.SharedSQLiteStatement.acquire(SharedSQLiteStatement.java:87)
        at com.genaut.myapp.database.dao.DaoSounds_Impl.deleteAllSounds(DaoSounds_Impl.java:140)
        at com.genaut.myapp.database.DatabaseSounds$1.onOpen(DatabaseSounds.java:57)
        at com.genaut.myapp.database.DatabaseSounds_Impl$1.onOpen(DatabaseSounds_Impl.java:65)
        at android.arch.persistence.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:111)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:149)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:266)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
        at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:233)
        at com.genaut.myapp.database.dao.DaoSounds_Impl.getAll(DaoSounds_Impl.java:155)
        at com.genaut.myapp.Home$LoadGridAsyncTask.doInBackground(Home.java:83)
        at com.genaut.myapp.Home$LoadGridAsyncTask.doInBackground(Home.java:78)
        at android.os.AsyncTask$2.call(AsyncTask.java:305)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
        at java.lang.Thread.run(Thread.java:761)

Это метод Дао:

@Query("SELECT * FROM entitysounds")
    List<EntitySounds> getAll();

Ответы [ 3 ]

0 голосов
/ 01 января 2019

Мой друг, у меня была похожая проблема.но для меня проблема была в том, что я получаю базу данных из двух разных классов.Когда удалили вторую инициализацию из второго класса, это сработало.

0 голосов
/ 03 марта 2019

Это происходит потому, что onOpen() обратного вызова вызывается, когда уже вызван getDatabase.

Затем со строкой INSTANCE.soundsDao().deleteAllSounds(), если вы посмотрите на реализацию deleteAllSounds() в SoundsDao_Impl (генерируемый файл Impl Dao s), вы увидите, что он вызывает __db.beginTransaction(), что вызовет mOpenHelper.getWritableDatabase().

Здесь Exception выбрасывается getDatabase called recursively.

Исправление может быть помещено INSTANCE.soundsDao().deleteAllSounds() в другой поток, как показано в этой ссылке: https://medium.com/androiddevelopers/7-pro-tips-for-room-fbadea4bfbd1

ioThread {
    INSTANCE.soundsDao().deleteAllSounds()
}

...

private val IO_EXECUTOR = Executors.newSingleThreadExecutor()

/**
 * Utility method to run blocks on a dedicated background thread, used for io/database work.
 */
fun ioThread(f : () -> Unit) {
    IO_EXECUTOR.execute(f)
}

Ссылка здесь: https://gist.github.com/florina-muntenescu/697e543652b03d3d2a06703f5d6b44b5

0 голосов
/ 09 июня 2018

но затем я использую дао для получения информации из базы данных

Это не будет работать, так как Комната еще не настроена.Либо:

  • Выполните эту работу за пределами RoomDatabase.Callback, либо

  • Не используйте Комнату внутри RoomDatabase.Callback, но вместо этогоиспользуйте SupportSQLiteDatabase, который предоставляется как параметр для onOpen(), а другие методы обратного вызова

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...