〈kotlin〉Room③ データベースインスタンス

Android studioでkotlinを使ってAndroidアプリ作成の勉強中。

データベースSQLiteを簡単に扱うことができるRoomの実装をまとめる。

前回の記事の続き。
<kotlin> Room - ゆるプログラミング日記

「データベースのインスタンスは高コストで通常アプリに1つで良いためシングルトンにする」を解決したい。

データベースクラスの作成

RoomDatabaseを拡張する抽象クラスとDAOインスタンスを返す抽象メソッドを定義。
データベースが存在しない場合はデータベースを作成し、
一度作成した後は既存のデータベースを返すメソッドをコンパニオンオブジェクトで定義する。

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

   abstract fun itemDao(): ItemDao

   companion object {
       @Volatile
       private var INSTANCE: ItemRoomDatabase? = null

       fun getDatabase(context: Context): ItemRoomDatabase {
           return INSTANCE ?: synchronized(this) {
               val instance = Room.databaseBuilder(
                   context.applicationContext,
                   ItemRoomDatabase::class.java,
                   "item_database"
               )
                   .fallbackToDestructiveMigration()
                   .build()
               INSTANCE = instance
               return instance
           }
       }
   }
}
  • exportSchema

データベースのスキーマをフォルダーにエクスポートするかどうか。
trueの場合エクスポートが行われ、スキーマのバージョン履歴を残せる。
デフォルトではtrueで、履歴を残さないデータベースはfalseを設定する。

  • @Volatile

アノテーションをつけた変数はキャッシュに保存されなくなり、
書き込み読み込みが全てメインメモリとの間で行われる。
これにより値が常に最新になり、全ての実行スレッドで同じになる。

  • INSTANCE変数

データベース作成時に、データベースに対する参照を保持する。

  • getDatabase()メソッド

INSTANCE変数を返すか、
INSTANCE変数がnull(一度も作成されてない)の場合は初期化処理を行い、
作成したデータベースを返す。

  • synchronized

このコードブロックには一度に 1 つのスレッドしか入ることができず、
データベースの初期化が一度しか行われないようにする。
(これがないと複数のスレッドが競合状態になってデータベース インスタンスを同時に要求した時、
結果的に 1 つではなく 2 つのデータベースが作成される可能性がある。)

  • fallbackToDestructiveMigration()

スキーマが変更されたとき古いスキーマから新しいスキーマへの移行方法を定義した移行パスが必要になるが、
移行パスが見つからなかったらエラーが発生してしまう。
このオプションをつけると、
移行パスが見つからなければ古いデータは破棄してデータベースを再作成する。

データベースのインスタンス

Applicationクラス内でインスタンスを作成する。

class MyApplication : Application(){
   val database: ItemRoomDatabase by lazy { ItemRoomDatabase.getDatabase(this) }
}

lazy デリゲートを使用して、アプリの起動時ではなく最初にアクセスされたときに
上記で作成したgetDatabase()が呼び出されてデータベースインスタンスが作成される。
Applicationクラスは、AndroidManifest.xmlのapplicationタグ内に、
android:name=".MyApplication"」として含めておく必要がある。
データベースが必要なときはこのクラス内から取得する。


参考
Room を使用してデータを永続化する  |  Android Developers
Room データベースを移行する  |  Android デベロッパー  |  Android Developers
Database  |  Android Developers