Room 永続ライブラリは、SQLite に抽象化レイヤを提供することで、 では、SQLite を最大限に活用しながら、より堅牢なデータベース アクセスを実現できます。この このページでは、Kotlin マルチプラットフォーム(KMP)プロジェクトで Room を使用する方法に焦点を当てます。詳細 Room の使用について詳しくは、Room を使用してローカル データベースにデータを保存するをご覧ください。 または公式サンプルをご覧ください。
依存関係をセットアップする
KMP をサポートしている Room の現在のバージョンは次のとおりです。 2.7.0-alpha01 以降
KMP プロジェクトで Room を設定するには、
モジュールの build.gradle.kts
ファイルに追加します。
androidx.room:room-gradle-plugin
- Room スキーマを構成するための Gradle プラグインandroidx.room:room-compiler
- コードを生成する KSP プロセッサandroidx.room:room-runtime
- ライブラリのランタイム部分androidx.sqlite:sqlite-bundled
- (省略可)バンドルされた SQLite ライブラリ
また、Room の SQLite ドライバを構成する必要があります。これらの要因は ターゲットプラットフォームに応じて 自動的に作成されます詳しくは、 ドライバの実装 を参照してください。
その他の設定情報については、以下をご覧ください。
で確認できます。データベース クラスの定義
DAO とともに @Database
アノテーション付きのデータベース クラスを作成する必要があります
共有 KMP モジュールの共通ソースセット内のエンティティを確認できます。配置
共通ソース内でこれらのクラスを使用すると、ターゲット
説明します。
インターフェースを使用して expect
オブジェクトを宣言する場合
RoomDatabaseConstructor
: Room コンパイラが actual
を生成します
あります。Android Studio が警告を発することがある
"Expected object 'AppDatabaseConstructor' has no actual declaration in
module"
、@Suppress("NO_ACTUAL_FOR_EXPECT")
を使用して警告を抑制できます。
// shared/src/commonMain/kotlin/Database.kt
@Database(entities = [TodoEntity::class], version = 1)
@ConstructedBy(AppDatabaseConstructor::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getDao(): TodoDao
}
// The Room compiler generates the `actual` implementations.
@Suppress("NO_ACTUAL_FOR_EXPECT")
expect object AppDatabaseConstructor : RoomDatabaseConstructor<AppDatabase> {
override fun initialize(): AppDatabase
}
@Dao
interface TodoDao {
@Insert
suspend fun insert(item: TodoEntity)
@Query("SELECT count(*) FROM TodoEntity")
suspend fun count(): Int
@Query("SELECT * FROM TodoEntity")
fun getAllAsFlow(): Flow<List<TodoEntity>>
}
@Entity
data class TodoEntity(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val title: String,
val content: String
)
なお、実際の宣言 / 期待される宣言を必要に応じて使用できます。
を使用してプラットフォーム固有の Room 実装を作成します。たとえば、
共通のコードで定義されるプラットフォーム固有の DAO。expect
を使用して
プラットフォーム固有のクエリを追加して actual
定義を指定する
ソースセットです
データベース ビルダーの作成
各プラットフォームで Room をインスタンス化するために、データベース ビルダーを定義する必要があります。この
プラットフォーム固有のソースに配置する必要がある API の唯一の部分
異なるためです。たとえば Android では
データベースの場所は通常、
Context.getDatabasePath()
API を使用します。iOS の場合、データベースのロケーションは
NSFileManager
を使用して取得できます。
Android
データベース インスタンスを作成するには、データベースとともに [Context] を指定します。 あります。
// shared/src/androidMain/kotlin/Database.kt
fun getDatabaseBuilder(ctx: Context): RoomDatabase.Builder<AppDatabase> {
val appContext = ctx.applicationContext
val dbFile = appContext.getDatabasePath("my_room.db")
return Room.databaseBuilder<AppDatabase>(
context = appContext,
name = dbFile.absolutePath
)
}
iOS
データベース インスタンスを作成するには、
NSFileManager
(通常は NSDocumentDirectory
にあります)。
// shared/src/iosMain/kotlin/Database.kt
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFilePath = documentDirectory() + "/my_room.db"
return Room.databaseBuilder<AppDatabase>(
name = dbFilePath,
)
}
private fun documentDirectory(): String {
val documentDirectory = NSFileManager.defaultManager.URLForDirectory(
directory = NSDocumentDirectory,
inDomain = NSUserDomainMask,
appropriateForURL = null,
create = false,
error = null,
)
return requireNotNull(documentDirectory?.path)
}
JVM(デスクトップ)
データベース インスタンスを作成するには、Java または Kotlin を使用してデータベース パスを指定します API
// shared/src/jvmMain/kotlin/Database.kt
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFile = File(System.getProperty("java.io.tmpdir"), "my_room.db")
return Room.databaseBuilder<AppDatabase>(
name = dbFile.absolutePath,
)
}
データベースのインスタンス化
プラットフォーム固有の API から RoomDatabase.Builder
を取得したら、
Room データベースの残りの部分は共通のコードで構成できます。
実際のデータベースのインスタンス化も
一緒に行います
// shared/src/commonMain/kotlin/Database.kt
fun getRoomDatabase(
builder: RoomDatabase.Builder<AppDatabase>
): AppDatabase {
return builder
.addMigrations(MIGRATIONS)
.fallbackToDestructiveMigrationOnDowngrade()
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}
SQLiteDriver の選択
上記のコード スニペットでは BundledSQLiteDriver
を使用しています。これが
推奨ドライバには、ソースからコンパイルされた SQLite が含まれます。
すべてのプラットフォームで最も整合性の高い最新バージョンの SQLite を提供すること。もし
OS 提供の SQLite を使用する場合は、プラットフォーム固有の setDriver
API を使用します。
プラットフォーム固有のドライバを指定するソースセットです。Android の場合は、次のコマンドを使用します。
AndroidSQLiteDriver
。iOS の場合は NativeSQLiteDriver
を使用できます。宛先
NativeSQLiteDriver
を使用するには、リンカー オプションを提供して、iOS アプリが
アプリをシステム SQLite と動的にリンクします。
// shared/build.gradle.kts
kotlin {
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "TodoApp"
isStatic = true
// Required when using NativeSQLiteDriver
linkerOpts.add("-lsqlite3")
}
}
}
相違点
Room はもともと Android ライブラリとして開発され、その後 API の互換性に重点を置いた KMP。Room の KMP バージョンは多少異なる プラットフォーム間の違いや Android 固有のバージョンからの違いですこれらの違いは、 以下で説明します。
ブロック DAO 関数
Room for KMP を使用する場合、Android 以外のプラットフォーム用にコンパイルされたすべての DAO 関数が
リアクティブの戻り値の型を除き、suspend
関数にする必要があります。
Flow
として。
// shared/src/commonMain/kotlin/MultiplatformDao.kt
@Dao
interface MultiplatformDao {
// ERROR: Blocking function not valid for non-Android targets
@Query("SELECT * FROM Entity")
fun blockingQuery(): List<Entity>
// OK
@Query("SELECT * FROM Entity")
suspend fun query(): List<Entity>
// OK
@Query("SELECT * FROM Entity")
fun queryFlow(): Flow<List<Entity>>
// ERROR: Blocking function not valid for non-Android targets
@Transaction
fun blockingTransaction() { // … }
// OK
@Transaction
suspend fun transaction() { // … }
}
豊富な機能を備えた非同期 kotlinx.coroutines
ライブラリが Room で利用できる
複数のプラットフォームに
利用できます最適な機能を得るには、suspend
関数は、KMP プロジェクトでコンパイルされた DAO に適用されます。ただし、例外として
既存の DAO との下位互換性を維持するための Android 固有の DAO
学びました。
KMP との機能の違い
このセクションでは、KMP と Android プラットフォームの機能の違いについて説明します。 できません。
@RawQuery DAO 関数
Android 以外のプラットフォーム用にコンパイルされた、@RawQuery
アノテーション付きの関数
代わりに RoomRawQuery
型のパラメータを宣言し、
SupportSQLiteQuery
。
@Dao
interface TodoDao {
@RawQuery
suspend fun getTodos(query RoomRawQuery): List<TodoEntity>
}
RoomRawQuery
を使用すると、実行時にクエリを作成できます。
suspend fun getTodosWithLowercaseTitle(title: String): List<TodoEntity> {
val query = RoomRawQuery(
sql = "SELECT * FROM TodoEntity WHERE title = ?"
onBindStatement = {
it.bindText(1, title.lowercase())
}
)
return todosDao.getTodos(query)
}
クエリ コールバック
クエリ コールバックを構成するための次の API は、一般的には使用できない Android 以外のプラットフォームでは使用できません。
RoomDatabase.Builder.setQueryCallback
RoomDatabase.QueryCallback
Room の今後のバージョンで、クエリ コールバックのサポートを追加する予定です。
クエリ コールバックを使用して RoomDatabase
を構成する API
RoomDatabase.Builder.setQueryCallback
とコールバック インターフェース
RoomDatabase.QueryCallback
は共通で使用できないため、使用できません
Android 以外のプラットフォームでも利用できます
データベースの自動終了
タイムアウト後の自動終了を有効にする API
RoomDatabase.Builder.setAutoCloseTimeout
は、Android でのみご利用いただけます。
他のプラットフォームでは利用できません。
パッケージ化前のデータベース
次の API を使用して、RoomDatabase
既存のデータベース(
事前パッケージ化済みデータベースなど)は、一般的には利用できないため、
Android 以外のプラットフォームで利用できますこれらの API は次のとおりです。
RoomDatabase.Builder.createFromAsset
RoomDatabase.Builder.createFromFile
RoomDatabase.Builder.createFromInputStream
RoomDatabase.PrepackagedDatabaseCallback
次のバージョンで、事前パッケージ化済みデータベースのサポートを追加する予定です。 会議室。
マルチインスタンスの無効化
複数インスタンスの無効化を有効にする API
RoomDatabase.Builder.enableMultiInstanceInvalidation
は以下でのみご利用いただけます:
一般的なプラットフォームや他のプラットフォームでは利用できません。