カテゴリー
Kotlin言語

Android:Kotlin: Room でデータベースを利用する

Android Studio(Kotlin)でのアプリ作成でデータベース(SQLite)を Room を使って利用してみます。あらかじめ用意されたデータベースファイルを読み込んでみます


説明用のコードは Android Developper にある「SQLの基本」のスターターコードを基本にしました

  • SQLite の操作を Room を介して行います
  • データベースの処理部分にコルーチン(coroutine)を使います

データベースの操作は非同期で

  • アプリでデータベースを操作すると、結果が返ってくるまで時間がかかることがあります。
  • 時間のかかる処理でアプリがフリーズしたように見えないよう、非同期で処理を行うようにします
  • 今回は非同期の処理にコルーチン(coroutine)を使ってみます

コルーチン(coroutine)とは

  • 非同期の処理を簡単に記述できる方法です
  • GlobalScope.launch{ ・・・ } のようにすると、launch 内の処理は非同期で実行されます
  • コルーチン内で利用する関数に suspend をつけるとメインの処理をブロックせずに、中断・再開によって効率よく処理されるようです

データベースを使う手順

  1. アプリの build.gradle に Room , Coroutine を使うための設定(依存関係)を追加します
  2. 最初に読み込む SQLite のデータベースファイルを用意
  3. エンティティ(テーブル)のクラスを作成
  4. データベース操作用のクラス(DAOクラス)を作成
  5. データベース生成用のクラス を作成
  6. データベースを利用するためのコードの記述

設定やコードは、お決まりと思って真似してみますね

build.gradle の設定

Android Studio でアプリのプロジェクトを開いたら、build.gradle(アプリ)に次の行を追加します

dependencies {
    def room_version = '2.3.0'

    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'

    ・・・
}

最初に読み込む SQLite のデータベースファイルを用意

  • 今回は、スターターコードにあらかじめ用意されている sql_basics.db を使います
  • SQLite のデータベースは、あらかじめ Windows 版の SQLite などで作成しておくことができます
  • 用意したデータベースファイルは、Android Studio の assets/database に置きます

エンティティ(テーブル)のクラスの作成

  • ここでは SQLite の park テーブルを、CaliforniaPark クラスとして作成しています
  • SQLite でのテーブル名と、Room で扱うクラス名が同じときは @Entity の tableName を省略できます
  • SQLite でのカラム名と、Room で扱うプロパティ名が同じときは @ColumnInfo の name は省略できます
  • つまり、クラス名やプロパティ名は、データベースのテーブル名とカラム名に一致させておくと記述は楽になります
  • 尚、大文字と小文字が違っても同じとみなします
@Entity(tableName = "park")
data class CaliforniaPark(
    @PrimaryKey(autoGenerate = true) val id: Int,
    @ColumnInfo(name = "name") val name: String,
    @ColumnInfo(name = "city") val city: String,
    @ColumnInfo(name = "area_acres") val acres: Int,
    @ColumnInfo(name = "park_visitors") val visitors: Int?,
    @ColumnInfo(name = "established") val established: Long,
    @ColumnInfo(name = "type") val type: String
)

データベース操作用のクラス(DAOクラス)の作成

  • ここでは CaliforniaPark クラス(エンティティ)を操作するための CaliforniaParkDao インタフェースを作成しています
  • データベースを操作するクエリーを、Kotlin の関数に結び付けます
  • コルーチン内で使う関数なので、suspend を付けておきます
@Dao
interface CaliforniaParkDao {
@Insert
suspend fun insertAll(parks: List<CaliforniaPark>)
@Query("SELECT * FROM park")
suspend fun getAll(): List<CaliforniaPark>
}

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

  • データベースのインスタンスを生成する AppDatabase クラスを作成します
  • データベースのインスタンスを返す getDatabase() メソッドを含みます
  • CaliforniaParkDao を返す californiaParkDao() メソッドを含みます
  • アプリで使うデータベースファイルの名前は app_database としています
  • 最初にデータを設定するのに使う SQLite データベースは sql_basics.db です。createFromAsset(“database/sql_basics.db”) として設定します
  • このコードはテンプレ的に使います
@Database(entities = arrayOf(CaliforniaPark::class), version = 1)
abstract class AppDatabase: RoomDatabase() {
abstract fun californiaParkDao(): CaliforniaParkDao

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

fun getDatabase(
context: Context
): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context,
AppDatabase::class.java,
"app_database"
)
.createFromAsset("database/sql_basics.db")
.build()
INSTANCE = instance

instance
}
}
}
}

データベースを利用するためのコード

  • 今回は MainActivity.kt からデータベースを利用してみます
  • AppDatabase の getDatabase() でデータベースのインスタンスを取得します
  • データベースインスタンスの californiaParkDao() メソッドを使って、CaliforniaParkDao の getAll() を呼び出します
  • getAll() は、エンティティ(CaliforniaPark)で関連付けられた park テーブル(SQLiteデータベース)のデータを、リストとして返します
class MainActivity : AppCompatActivity() {
    ・・・
    override fun onCreate(savedInstanceState: Bundle?) {
        ・・・
        GlobalScope.launch {
            AppDatabase.getDatabase(applicationContext).californiaParkDao().getAll().forEach {
            Log.d("MainActivity","${it.name}")
        }
    }
}