アプリケーションが始めて起動した直後に、データの事前取り込み(初期状態の設定)を必要とする場合があります。
事前取り込みの方法ついて、まとめました。
Room(Android Jetpack)でデータベースを構築した場合です。
※環境:Android Studio Ladybug | 2024.2.1 Patch 3
Kotlin 2.0.0
androidx.sqlite:sqlite:2.4.0
androidx.room:room-*:2.6.1
DB Browser for SQLite バージョン 3.13.1
※サンプルの全体像は「Roomでデータベースを構築」を参照
事前取り込みとは
「事前取り込み」とは、アプリケーションが始めて起動した直後の、データベースの初期状態を設定することです。
事前取り込みが必要かどうかはアプリケーションに依存します。ですので、事前取り込みはオプション的な実装です。
事前取り込みの実装
Roomは初期状態をファイルから取り込む機能を持っています。以下は、assetsフォルダから取り込む例です。
@Database(entities = arrayOf(Player::class), version = 1) abstract class GameDb : RoomDatabase() { abstract fun playerDao(): PlayerDao companion object { @Volatile private var instance: GameDb? = null fun getDatabase(context: Context): GameDb { return instance ?: synchronized(this) { val _instans = Room.databaseBuilder( context, GameDb::class.java, "Game.db" ) .createFromAsset("databases/Game.db") // 初期状態 .build() instance = _instans _instans } } } }
ただし、データベース識別子と初期状態は、スキーマが一致していなければなりません。
不一致の場合はエラーになり、アプリは起動しません。
事前データの作成
データベースの初期状態を「事前データ」といいます。
「ツール:DB Browser for SQLite」を用いた、事前データの作成方法を紹介します。
※DB Browser for SQLiteについては「データベースの閲覧」を参照
スキーマ情報のダンプ
事前データの作成で必要なスキーマ情報をダンプします。
build.gradle.ktsファイルにスキーマ情報のダンプ先フォルダを指定して下さい。
plugins { ... } android { namespace = "com.example.game" compileSdk = 35 defaultConfig { ... } buildTypes { ... } compileOptions { ... } kotlinOptions { ... } buildFeatures { ... } ksp { arg("room.schemaLocation", "$projectDir/schemas") } } dependencies { ... }
※「exportSchema = true」はスキーマのダンプを有効化するフラグです。デフォルトがtrueなので、指定の必要はありません。
@Database(entities = arrayOf(Player::class), version = 1, exportSchema = true) abstract class GameDb : RoomDatabase() { abstract fun playerDao(): PlayerDao // Daoの提供(必須) companion object { ... } }
アプリを実行すると、指定したフォルダにスキーム情報(jsonファイル)がダンプされます。実行の必要な点が難点です。
{ "formatVersion": 1, "database": { "version": 1, "identityHash": "1389462589b209bcd420685744427f6a", "entities": [ { "tableName": "Player", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `score` INTEGER NOT NULL)", "fields": [ { "fieldPath": "id", "columnName": "id", "affinity": "INTEGER", "notNull": true }, { "fieldPath": "name", "columnName": "name", "affinity": "TEXT", "notNull": true }, { "fieldPath": "score", "columnName": "score", "affinity": "INTEGER", "notNull": true } ], "primaryKey": { "autoGenerate": true, "columnNames": [ "id" ] }, "indices": [], "foreignKeys": [] } ], "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1389462589b209bcd420685744427f6a')" ] } }
スキーマ情報の「identityHashの値」は「entitiesの値」のハッシュ値です。Roomのシステムは、この値を用いてスキーマの一致を確認しています。
データベースの作成
SQLのコマンドファイル(GameDb.sql)を作成します。
スキーマ情報(jsonファイル)のハイライト部分を抜き出した物です。ただし、テーブル名(${TABLE_NAME})は置き換えて下さい。
CREATE TABLE IF NOT EXISTS `Player` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `score` INTEGER NOT NULL); CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT); INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1389462589b209bcd420685744427f6a'); ※コマンドラインの終わりはセミコロン「;」です。
コマンドファイルをツールにインポートすれば、データベースが作成されます。
Rowデータの登録
必要なRowデータを登録して変更を書き込めば、事前データの作成完了です。
作成した事前データは、プロジェクトのassetsフォルダへ、コピー&ペーストして下さい。
事前取り込みの結果
アプリが始めて起動した直後に事前取り込みしたデータが表示されます。
関連記事: