Oda (Kotlin Multiplatform)

Oda kalıcılık kitaplığı, SQLite üzerinde bir soyutlama katmanı sağlar. Böylece, daha güçlü veritabanı erişimi sağlar ve SQLite'ın tüm gücünden yararlanır. Bu sayfa, Kotlin Multiplatform (KMP) projelerinde Room'un kullanılmasına odaklanmaktadır. Oda kullanımı hakkında daha fazla bilgi için Oda'yı kullanarak verileri yerel bir veritabanına kaydetme bölümüne veya resmi örneklerimize bakın.

Bağımlılıkları ayarlama

Oda'nın KMP'yi destekleyen mevcut sürümü 2.7.0-alpha01 veya sonraki bir sürümdür.

KMP projenizde Room'u kurmak için modülünüzün build.gradle.kts dosyasına yapıların bağımlılıklarını ekleyin:

  • androidx.room:room-gradle-plugin - Oda şemalarını yapılandırmak için Gradle Eklentisi
  • androidx.room:room-compiler - Kod oluşturan KSP işlemcisi
  • androidx.room:room-runtime - Kitaplığın çalışma zamanı kısmı
  • androidx.sqlite:sqlite-bundled - (İsteğe bağlı) Paket haline getirilen SQLite kitaplığı

Buna ek olarak, odanın SQLite sürücüsünü yapılandırmanız gerekir. Bu sürücüler, hedef platforma göre farklılık gösterir. Mevcut sürücü uygulamalarının açıklamaları için Sürücü uygulamaları bölümüne bakın.

Ek kurulum bilgileri için aşağıdakilere bakın:

Veritabanı sınıflarını tanımlama

Paylaşılan KMP modülünüzün ortak kaynak kümesindeki DAO'lar ve varlıklarla birlikte @Database ek açıklamasına sahip bir veritabanı sınıfı oluşturmanız gerekir. Bu sınıfların ortak kaynaklara yerleştirilmesi, tüm hedef platformlarda paylaşılmasına olanak tanır.

// shared/src/commonMain/kotlin/Database.kt

@Database(entities = [TodoEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
  abstract fun getDao(): TodoDao
}

@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
)

Platforma özel Oda uygulamaları oluşturmak için gerçek / beklenen bildirimleri kullanabileceğinizi unutmayın. Örneğin, expect kullanarak ortak kodda tanımlanmış platforma özgü bir DAO ekleyebilir ve ardından actual tanımlarını platforma özel kaynak kümelerindeki ek sorgularla belirtebilirsiniz.

Veritabanı oluşturucuyu oluşturma

Her platformda Room örneğini oluşturmak için bir veritabanı oluşturucu tanımlamanız gerekir. Bu, dosya sistemi API'lerindeki farklılıklar nedeniyle platforma özel kaynak kümelerinde bulunması gereken API'nin tek parçasıdır. Örneğin, Android'de veritabanı konumu genellikle Context.getDatabasePath() API aracılığıyla, iOS'te ise veritabanı konumu NSHomeDirectory kullanılarak alınır.

Android

Veritabanı örneğini oluşturmak için veritabanı yoluyla birlikte bir Context belirtin. Veritabanı fabrikası belirtmeniz gerekmez.

// 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

Veritabanı örneği oluşturmak için veritabanı yoluyla birlikte bir veritabanı fabrikası sağlayın. Veritabanı fabrikası, adı KClass<T> türünde bir alıcıyla instantiateImpl olan oluşturulmuş bir uzantı işlevini çağıran bir lambda işlevidir. Burada T, @Database ek açıklamalı sınıfının türüdür.

// shared/src/iosMain/kotlin/Database.kt

fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
    val dbFilePath = NSHomeDirectory() + "/my_room.db"
    return Room.databaseBuilder<AppDatabase>(
        name = dbFilePath,
        factory =  { AppDatabase::class.instantiateImpl() }
    )
}

JVM (Masaüstü)

Veritabanı örneğini oluşturmak için yalnızca veritabanı yolunu belirtin. Veritabanı fabrikası sağlamanız gerekmez.

// shared/src/commonMain/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,
    )
}

Veritabanı örneği oluşturma

Platforma özel kurucuların birinden RoomDatabase.Builder edindikten sonra Room veritabanının geri kalanını gerçek veritabanı örneklendirmesiyle birlikte ortak kodda yapılandırabilirsiniz.

// 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 seçme

Önceki kod snippet'lerinde BundledSQLiteDriver kullanılmıştır. Bu, kaynaktan derlenen SQLite'ı içeren ve tüm platformlarda en tutarlı ve güncel SQLite sürümünü sunan, önerilen sürücüdür. OS tarafından sağlanan SQLite'ı kullanmak isterseniz platforma özgü bir sürücü belirten platforma özgü kaynak kümelerinde setDriver API'yi kullanın. Android'de AndroidSQLiteDriver, iOS'te ise NativeSQLiteDriver kullanılabilir. NativeSQLiteDriver özelliğini kullanmak için iOS uygulamasının sistem SQLite'sine dinamik olarak bağlanmasını sağlayacak bir bağlayıcı seçeneği sağlamanız gerekir.

// 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")
        }
    }
}

Farklılıklar

Room, başlangıçta Android kitaplığı olarak geliştirildi ve daha sonra API uyumluluğuna odaklanarak KMP'ye taşındı. Room'un KMP sürümü, platformlar arasında ve Android'e özgü sürümden biraz farklıdır. Bu farklılıklar aşağıda listelenmiştir ve açıklanmıştır.

DAO işlevlerini engelleme

KMP için Room kullanılırken Android dışı platformlar için derlenen tüm DAO işlevlerinin, Flow gibi reaktif dönüş türleri hariç suspend işlevi olması gerekir.

// 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() { // … }
}

Oda, Kotlin'in birden fazla platformda zengin özelliklere sahip eşzamansız kotlinx.coroutines kitaplığından yararlanabiliyor. suspend işlevleri, mevcut kod tabanıyla geriye dönük uyumluluğu korumak amacıyla Android'e özel DAO'lar haricinde, bir KMP projesinde derlenen DAO'lar için en uygun işlevi sağlamak amacıyla zorunlu kılınır.

KMP ile özellik farklılıkları

Bu bölümde, oda özelliklerinin KMP ve Android platformu sürümleri arasında nasıl farklılık gösterdiği açıklanmaktadır.

@RawQuery DAO işlevleri

Android dışı platformlar için derlenen ve @RawQuery ek açıklamasına sahip olan işlevler hata verir. Room'un gelecekteki bir sürümünde @RawQuery desteği eklemeyi planlıyoruz.

Sorgu Geri Çağırması

Sorgu geri çağırmalarını yapılandırmaya yönelik aşağıdaki API'ler ortak olarak mevcut olmadığından Android dışındaki platformlarda kullanılamaz.

  • RoomDatabase.Builder.setQueryCallback
  • RoomDatabase.QueryCallback

Odanın gelecekteki bir sürümünde sorgu geri çağırma desteği eklemeyi planlıyoruz.

RoomDatabase.QueryCallback geri çağırma arayüzüyle birlikte sorgu geri çağırma (RoomDatabase.Builder.setQueryCallback) içeren bir RoomDatabase yapılandıran API yaygın olarak kullanılmadığı için Android dışındaki diğer platformlarda kullanılamaz.

Veritabanını Otomatik Kapatma

Zaman aşımından (RoomDatabase.Builder.setAutoCloseTimeout) sonra otomatik kapanmayı etkinleştiren API yalnızca Android'de kullanılabilir ve diğer platformlarda kullanılamaz.

Paket Hazır Veritabanı

Mevcut bir veritabanı (yani, önceden paketlenmiş bir veritabanı) kullanarak RoomDatabase oluşturmak için aşağıdaki API'ler ortak olarak mevcut olmadığından Android dışındaki diğer platformlarda kullanılamaz. Bu API'ler şunlardır:

  • RoomDatabase.Builder.createFromAsset
  • RoomDatabase.Builder.createFromFile
  • RoomDatabase.Builder.createFromInputStream
  • RoomDatabase.PrepackagedDatabaseCallback

Room'un gelecekteki bir sürümünde önceden paketlenmiş veritabanları için destek eklemeyi planlıyoruz.

Çoklu Örnek Geçersiz Kılma

Çok örnekli geçersiz kılmayı etkinleştiren API olan RoomDatabase.Builder.enableMultiInstanceInvalidation yalnızca Android'de kullanılabilir, ortak platformlarda veya diğer platformlarda kullanılamaz.