Room 3.0, kitaplığı Kotlin'e öncelik verecek şekilde dönüştüren önemli bir ana sürüm güncellemesidir. Kotlin Multiplatform (KMP) desteği sunar, Kotlin Symbol Processing (KSP) gerektirir ve eşzamansız işlemler için coroutine'leri zorunlu kılar.
Mevcut Room 2.x uygulamaları ve geçişli bağımlılıklarla uyumluluk sorunlarını önlemek için Room 3.0 yeni bir pakette bulunur: androidx.room3.
Bu kılavuzda, mevcut Room 2.x uygulamanızı Room 3.0'a taşımak için gereken adımlar açıklanmaktadır.
Room 3.0'daki önemli değişiklikler
Taşıma işlemine başlamadan önce temel farklılıklar hakkında bilgi edinin:
- Yeni paket ve yapılar: Tüm sınıflar
androidx.room3içinde yer alır. Yadigârlar,room3önekini kullanır (ör.androidx.room3:room3-runtime). - Yalnızca Kotlin ve KSP: Room 3.0, Java kodu oluşturmayı desteklemez. KAPT veya Java ek açıklama işlemcileri yerine KSP'yi kullanın. Room 3.0, giriş olarak Java kaynaklarını desteklemeye devam ediyor.
- Öncelikli olarak eş yordamlar: Gözlemlenebilir türler hariç, DAO işlevleri
suspendişlevleri olmalıdır.CoroutineContext, yürütücülerin yerini alır. - No SupportSQLite:
SQLiteDriverAPI'leri Room'u destekler. Oda, temel API'lerdenSupportSQLiteDatabasekaldırılıyor. - API değişiklikleri: Taşıma işlemleri ve veritabanı geri çağırmaları,
SupportSQLiteDatabaseyerineSQLiteConnectionkullanır. - Reaktif türler için dönüştürücüler: RxJava, LiveData, Guava ve Paging
dönüş türleri için
@DaoReturnTypeConverterskaydetmeniz gerekir.
İki ayrı aşamada geçiş yapmanızı öneririz: İlk olarak Room 2.x'te kod tabanınızı hazırlayıp modernize edin, ardından Room 3.0'a geçin.
Room 2.x'te hazırlık ve modernleştirme
Room 3.0'a geçmeden önce, Room 2.8 gibi mevcut Room 2.x sürümüne güncelleyerek modernizasyon çalışmalarının çoğunu gerçekleştirebilirsiniz. Room 2.8, Kotlin Multiplatform'u (KMP) destekler ve Room 3.0'ın kullandığı birçok sürücü API'si içerir.
Room 2.8 ve sonraki sürümlere güncelleme
Mevcut Room 2.x sürümünü kullanmak için derleme yapılandırmanızı güncelleyin:
[versions]
room2 = "2.8.4" # Use the current Room 2.8 version
[libraries]
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room2" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room2" }
KAPT'den KSP'ye taşıma
Room 3.0, Java ek açıklama işlemcilerini veya KAPT'yi desteklemez. Kotlin Symbol Processing (KSP) kullanmanız gerekir. Bu geçişi Room 2.x'te kalmaya devam ederken yapabilirsiniz.
Modülünüzün
build.gradle.ktsbölümünde KSP eklentisini uygulayın:plugins { id("com.google.devtools.ksp") version "<ksp_version>" }KSP sürümünün Kotlin sürümünüzle uyumlu olduğundan emin olun.
Oda derleyicisi bağımlılığı için
kaptveyaannotationProcessoryerinekspkullanın:dependencies { implementation(libs.androidx.room.runtime) ksp(libs.androidx.room.compiler) }
Eş yordamları kullanma
Room 3.0, eşzamansız işlemler için eş yordamlar gerektirir.
- DAO'larınızı güncelleyin:
Flowveya RxJava türleri gibi gözlemlenebilir bir reaktif tür döndürmedikleri sürece tüm DAO işlevlerisuspendişlevleri olmalıdır.
// Before (Blocking)
@Dao
interface UserDao {
@Query("SELECT * FROM User")
fun getAll(): List<User>
}
// After (Suspend)
@Dao
interface UserDao {
@Query("SELECT * FROM User")
suspend fun getAll(): List<User>
}
RoomDatabase'nizi veritabanı işlemlerini gerçekleştirmek için özel birExecutorile yapılandırdıysanız oluşturucudakisetQueryCoroutineContext'ü kullanarakCoroutineContext'e taşıyın:
Room.databaseBuilder<AppDatabase>(context, "db")
.setQueryCoroutineContext(Dispatchers.IO)
.build()
Sürücü API'lerini kullanın ve Support SQLite'den kaçının
Room 3.0, SQLiteDriver tarafından tam olarak desteklenir ve temel API'lerinde artık SupportSQLiteDatabase desteklenmez.
Veritabanı oluşturucunuzda setDriver ayarlamak için SQLiteDriver işlevini çağırmazsanız Room 2.8, hem Support SQLite hem de Driver API'lerinin çalıştığı bir uyumluluk modunda çalışır. Bu uyumluluk modu, sürücüyü etkinleştirmeden önce kod tabanınızı kademeli olarak dönüştürmenize olanak tanır.
- Dönüşüm taşıma işlemleri:
MigrationveAutoMigrationSpecalt sınıflarınızıSupportSQLiteDatabaseyerineSQLiteConnectionkullanacak şekilde taşıyın.
// Before (SupportSQLiteDatabase)
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE User ADD COLUMN age INTEGER DEFAULT 0 NOT NULL")
}
}
// After (SQLiteConnection - Room 2.8)
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.execSQL
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(connection: SQLiteConnection) {
connection.execSQL(
"ALTER TABLE User ADD COLUMN age INTEGER DEFAULT 0 NOT NULL"
)
}
}
- Veritabanı geri çağırmalarını dönüştürme:
RoomDatabase.CallbackuygulamalarınıSQLiteConnectionkullanacak şekilde güncelleyin:
// Before (SupportSQLiteDatabase)
val callback = object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
// ...
}
}
// After (SQLiteConnection - Room 2.8)
val callback = object : RoomDatabase.Callback() {
override fun onCreate(connection: SQLiteConnection) {
// ...
}
}
@RawQueryDAO işlevlerini dönüştürme:@RawQueryile açıklama eklenmiş işlevler içinSupportSQLiteQueryyerineRoomRawQuerykullanın:
// Before (SupportSQLiteQuery)
@Dao
interface UserDao {
@RawQuery
fun getUser(query: SupportSQLiteQuery): User
}
// After (RoomRawQuery)
@Dao
interface UserDao {
@RawQuery
suspend fun getUser(query: RoomRawQuery): User
}
Çalışma zamanında RoomRawQuery oluşturabilirsiniz:
val query = RoomRawQuery(
sql = "SELECT * FROM User WHERE id = ?",
onBindStatement = { statement ->
statement.bindInt(1, userId)
}
)
- İşlem API'lerini dönüştürme: Yalnızca Android'e özel
withTransactionverunInTransactionbloklarınıwithWriteTransactionveyawithReadTransactionile değiştirin:
// Before (withTransaction)
db.withTransaction {
// perform database operations
}
// After (withWriteTransaction - Room 2.8)
import androidx.room.withWriteTransaction
db.withWriteTransaction {
// perform database operations
}
İşlem bağlantısına doğrudan düşük düzeyde erişmeniz gerekiyorsa useWriterConnection ile immediateTransaction de kullanabilirsiniz.
SupportSQLiteDatabasedoğrudan kullanmaktan kaçının: HâlâSupportSQLiteDatabasegerektiren kapsamlı bir eski kodunuz varsa ve henüz bunu taşımadıysanızandroidx.room:room-sqlite-wrapperuyumluluk yapısını kullanın:
dependencies {
implementation("androidx.room:room-sqlite-wrapper:$roomVersion")
}
Ardından, getSupportWrapper kullanarak Room veritabanı örneğinizden SupportSQLiteDatabase elde edin:
import androidx.room.support.getSupportWrapper
val legacyDb: SupportSQLiteDatabase = roomDatabase.getSupportWrapper()
- SQLite sürücüsünü ayarlayın: Tüm Room API kullanımlarını sürücü API'lerine taşıdıktan sonra
BundledSQLiteDriverveyaAndroidSQLiteDrivergibi bir sürücüyüRoomDatabaseoluşturucunuzdasetDriver'i çağırarak yapılandırın:
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
val db = Room.databaseBuilder<AppDatabase>(context, "db")
.setDriver(BundledSQLiteDriver())
.build()
Akış tabanlı geçersiz kılma takibini kullanma
Room 2.8, InvalidationTracker.createFlow API'sini kullanıma sunar. Bu API'yi, Room 2.x'te kalmaya devam ederken eski InvalidationTracker.Observer uygulamalarından geçiş yapmak için kullanın. Bu, kod tabanınızı Observer'ı tamamen kaldıran Room 3.0'a hazırlar.
// Before (InvalidationTracker.Observer)
val observer = object : InvalidationTracker.Observer("User") {
override fun onInvalidated(tables: Set<String>) {
// reload user data
}
}
db.invalidationTracker.addObserver(observer)
// After (createFlow - Room 2.8)
val userFlow = db.invalidationTracker.createFlow("User").map { _ ->
userDao.getAllUsers()
}
Room 3.0'a taşıma
Uygulamanızı Room 2.x'te modernleştirdikten sonra Room 3.0'a geçmek için bağımlılıkları, paket içe aktarmalarını ve veritabanı geri çağırmalarını güncellemeniz gerekir.
Bağımlıları ve paket içe aktarmalarını güncelleme
- Derleme yapılandırmanızda
androidx.roombağımlılıklarınıandroidx.room3ile değiştirin:
[versions]
room3 = "3.0.0" # Use the current Room 3.0 version
[libraries]
androidx-room3-runtime = { module = "androidx.room3:room3-runtime", version.ref = "room3" }
androidx-room3-compiler = { module = "androidx.room3:room3-compiler", version.ref = "room3" }
- Bağımlılıklar bloğunuzu güncelleyin:
dependencies {
implementation(libs.androidx.room3.runtime)
ksp(libs.androidx.room3.compiler)
}
- Paket içe aktarma işlemlerinizi güncelleyin.
import androidx.room.*yerineimport androidx.room3.*koyun.
Tür dönüştürücü API'lerini güncelleme
Room 3.0, sütun değerlerini dönüştürme konusundaki kullanımlarını netleştirmek ve DAO dönüş türü dönüştürücülerle karışıklığı önlemek için tür dönüştürücü API'lerini yeniden adlandırır.
Kod tabanınızdaki aşağıdaki ek açıklamaları ve işlevleri güncelleyin:
@TypeConverteröğesini@ColumnTypeConverterolarak yeniden adlandırın.@TypeConvertersöğesini@ColumnTypeConvertersolarak yeniden adlandırın.@ProvidedTypeConverteröğesini@ProvidedColumnTypeConverterolarak yeniden adlandırın.RoomDatabase.Builder.addTypeConverteröğesiniaddColumnTypeConverterolarak yeniden adlandırın.
Örnek:
// Before
@ProvidedTypeConverter
class Converters {
@TypeConverter
fun fromTimestamp(value: Long?): Date? = ...
}
@Database(entities = [User::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase()
val db = Room.databaseBuilder<AppDatabase>(...)
.addTypeConverter(convertersInstance)
.build()
// After
import androidx.room3.ColumnTypeConverter
import androidx.room3.ColumnTypeConverters
import androidx.room3.ProvidedColumnTypeConverter
@ProvidedColumnTypeConverter
class Converters {
@ColumnTypeConverter
fun fromTimestamp(value: Long?): Date? = ...
}
@Database(entities = [User::class], version = 1)
@ColumnTypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase()
val db = Room.databaseBuilder<AppDatabase>(...)
.addColumnTypeConverter(convertersInstance)
.build()
İşlevleri askıya almak için geri çağırmaları güncelleyin
Room 3.0'da veritabanı geri çağırmaları ve taşımaları SQLiteConnection kullanır ve suspend işlevleridir.
- Manuel
Migrationsınıflarınızı güncelleyin:
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.async.executeSQL
val MIGRATION_1_2 = object : Migration(1, 2) {
override suspend fun migrate(connection: SQLiteConnection) {
connection.executeSQL(
"ALTER TABLE User ADD COLUMN age INTEGER DEFAULT 0 NOT NULL"
)
}
}
RoomDatabase.Callbackuygulamalarınızı güncelleyin:
val callback = object : RoomDatabase.Callback() {
override suspend fun onCreate(connection: SQLiteConnection) {
// ...
}
}
DAO dönüş türü dönüştürücülerini kaydetme
Room 3.0'da RxJava, LiveData, Guava ve Paging gibi reaktif dönüş türleri, @DaoReturnTypeConverters kullanarak DAO dönüş türü dönüştürücülerini kaydetmenizi gerektirir.
import androidx.room3.paging.PagingSourceDaoReturnTypeConverter
@Dao
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
interface UserDao {
@Query("SELECT * FROM User")
fun getAllPaginated(): PagingSource<Int, User>
}
- Sayfalama (
PagingSource):androidx.room3:room3-pagingyapısındanPagingSourceDaoReturnTypeConverterkaydettirin. - RxJava (
Observable,Flowable,Single,Maybe,Completable):androidx.room3:room3-rxjava3yapıtındanRxDaoReturnTypeConvertersöğesini kaydedin. - Guava (
ListenableFuture):androidx.room3:room3-guavayapısındanGuavaDaoReturnTypeConverteröğesini kaydedin. - LiveData (
LiveData):androidx.room3:room3-livedatayapısındanLiveDataDaoReturnTypeConverteröğesini kaydedin.
InvalidationTracker Observer'ın kaldırıldığını doğrulama
Room 3.0, InvalidationTracker.Observer ve addObserver ile removeObserver gibi ilgili kayıt yöntemlerini tamamen kaldırır.
1. aşamada henüz coroutine akışlarına geçiş yapmadıysanız tüm Observer kullanımlarını createFlow'e taşımanız gerekir:
val userFlow = db.invalidationTracker.createFlow("User").map { _ ->
userDao.getAllUsers()
}