使用 Room 递归调用 getDatabase

Gen*_*aut 3 android persistence android-room

当我尝试初始化我的数据库时出现错误。我正在使用 Android Room,我想使用 RoomDatabaseBuilder 来执行回调并填充我的数据库。

我在 Activity 类中执行 getDatabase 方法,但随后我使用 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;"
Run Code Online (Sandbox Code Playgroud)

崩溃的活动线来源:

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
Run Code Online (Sandbox Code Playgroud)

这是错误

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)
Run Code Online (Sandbox Code Playgroud)

这是道的方法:

@Query("SELECT * FROM entitysounds")
    List<EntitySounds> getAll();
Run Code Online (Sandbox Code Playgroud)

 

Com*_*are 8

但后来我使用 dao 从数据库中获取信息

这是行不通的,因为 Room 尚未设置。任何一个:

  • RoomDatabase.Callback, 或

  • 不要在 内部使用 Room RoomDatabase.Callback,而是使用SupportSQLiteDatabase作为参数提供给 的onOpen()和其他回调方法


DuD*_*uDu 6

发生这种情况是因为onOpen()已经有调用时才调用回调getDatabase

然后使用 line ,如果您查看in (Impl generated file of s)INSTANCE.soundsDao().deleteAllSounds()的实现,您可以看到它调用了which will call 。deleteAllSounds()SoundsDao_ImplDao__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)
}
Run Code Online (Sandbox Code Playgroud)

参考此处:https://gist.github.com/florina-muntenescu/697e543652b03d3d2a06703f5d6b44b5