web-dev-qa-db-ja.com

最初の実行時にAndroid Roomデータベーステーブルを設定するには?

SQLiteOpenHelperにはonCreate(SQLiteDatabase ...)メソッドがあり、これを使用してデータベーステーブルに初期データを設定しました。

最初のアプリの実行時にルームデータベーステーブルにデータを挿入する方法はありますか?

29
user2538289

データベースを作成した後、またはRoomDatabase.Callbackを使用してデータベースを開くたびにスクリプトを実行できます。このクラスは、Roomライブラリの最新バージョンで使用できます。

以下に示すように、RoomDatabase.CallbackonCreateおよびonOpenメソッドを実装し、RoomDatabase.Builderに追加する必要があります。

yourDatabase = Room.databaseBuilder(context, YourDatabase.class, "your db")
    .addCallback(rdc)
    .build();

RoomDatabase.Callback rdc = new RoomDatabase.Callback() {
    public void onCreate (SupportSQLiteDatabase db) {
        // do something after database has been created
    }
    public void onOpen (SupportSQLiteDatabase db) {
        // do something every time database is open
    }
};

参照

RoomDatabase.CallbackメソッドでRoom DAO自体を使用して、データベースを満たすことができます。完全な例については、「 ページネーションと部屋の例 」を参照してください

   RoomDatabase.Callback dbCallback = new RoomDatabase.Callback() {
        public void onCreate(SupportSQLiteDatabase db) {
            Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
                @Override
                public void run() {
                   getYourDB(ctx).yourDAO().insertData(yourDataList);
                }
            });
        }
    };
80
Arnav Rao

Arnav Raoが推奨するようにRoomDatabase.Callbackを使用しようとしましたが、コールバックを使用するには、データベースが構築される前にコールバックが作成されるため、DAOを使用できません。 db.insertとcontentの値を使用できますが、それが正しいとは思いませんでした。それでもう少し調べてみると-私は何年もかかりましたが-Googleが提供するサンプルを調べてみると、実際に答えを見つけました。

https://github.com/googlesamples/Android-architecture-components/blob/master/PersistenceContentProviderSample/app/src/main/Java/com/example/Android/contentprovidersample/data/SampleDatabase.Java

52行目と71行目のメソッドを参照してください-データベースインスタンスのビルド後、次の行はデータベースにレコードがあるかどうかを確認するメソッドを呼び出します(DAOを使用して)、それが空である場合初期データを挿入します(再びDAOを使用)。

これが立ち往生している他の誰にも役立つことを願っています:)

9
N1234

私はこれを行ういくつかの方法を試みましたが、それぞれ利用できませんでした。

最初に、 'addMigrations'メソッドを使用して移行実装をRoomに追加しようとしましたが、データベースのアップグレード中にのみ実行され、作成時には実行されないことがわかりました。

次に、 'openHelperFactory'メソッドを使用して、SQLiteOpenHelper実装をRoomに渡してみました。しかし、Roomのパッケージレベルのアクセス修飾子を回避するために多数のクラスを作成した後、私は努力を放棄しました。ルームのFrameworkSQLiteOpenHelperFactoryのサブクラス化も試みましたが、そのコンストラクターのパッケージレベルのアクセス修飾子はこれをサポートしていませんでした。

最後に、データを取り込むIntentServiceを作成し、ApplicationサブクラスのonCreateメソッドから呼び出しました。このアプローチは機能しますが、より良い解決策は、このページの他の場所でSinigamiが言及したトラッカーの問題に対する今後の修正です。

ダリル

[2017年7月19日追加]

この問題は、Room 1.0.0で解決されたように見えます。 Alpha5。このリリースでは、データベースが最初に作成されたときにコードを実行できるコールバックをRoomDatabaseに追加しました。を見てみましょう:

https://developer.Android.com/reference/Android/Arch/persistence/room/RoomDatabase.Callback.html

5
Darryl Staflund
@Provides
@Singleton
LocalDatabase provideLocalDatabase(@DatabaseInfo String dbName, Context context) {
    return Room.databaseBuilder(context, LocalDatabase.class, dbName)
            .addCallback(new RoomDatabase.Callback() {
                @Override
                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                    super.onCreate(db);
                    db.execSQL("INSERT INTO id_generator VALUES(1, 1, 1);");
                }
            })
//                .addMigrations(LocalDatabase.MIGRATION_1_2)
            .build();
}
1
nAkhmedov

データベースの作成後にテーブルにデータを入力できます。操作が別のスレッドで実行されていることを確認してください。以下のクラスに従って、最初にテーブルを事前設定できます。

AppDatabase.kt

@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {

        // For Singleton instantiation
        @Volatile private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(context, AppDatabase::class.Java, DATABASE_NAME)
                    .addCallback(object : RoomDatabase.Callback() {
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                            //pre-populate data
                            Executors.newSingleThreadExecutor().execute {
                                instance?.let {
                                    it.userDao().insertUsers(DataGenerator.getUsers())
                                }
                            }
                        }
                    })
                    .build()
        }
    }
}

DataGenerator.kt

class DataGenerator {

    companion object {
        fun getUsers(): List<User>{
            return listOf(
                User(1, "Noman"),
                User(2, "Aayan"),
                User(3, "Tariqul")
            )
        }
    }

}
0
Abu Noman