Room 3.0 ist ein wichtiges Versionsupdate, mit dem die Bibliothek auf Kotlin umgestellt wird. Es unterstützt Kotlin Multiplatform (KMP), erfordert Kotlin Symbol Processing (KSP) und erzwingt Koroutinen für asynchrone Vorgänge.
Um Kompatibilitätsprobleme mit vorhandenen Room 2.x-Apps und transitiven Abhängigkeiten zu vermeiden, befindet sich Room 3.0 in einem neuen Paket: androidx.room3.
In dieser Anleitung werden die Schritte beschrieben, die zum Migrieren Ihrer vorhandenen Room 2.x-Implementierung zu Room 3.0 erforderlich sind.
Wichtige Änderungen in Room 3.0
Machen Sie sich vor Beginn der Migration mit den wichtigsten Unterschieden vertraut:
- Neues Paket und neue Artefakte: Alle Klassen befinden sich in
androidx.room3. Artefakte verwenden dasroom3Präfix, z. B.androidx.room3:room3-runtime. - Nur Kotlin und KSP: Room 3.0 unterstützt keine Java-Code-Generierung. Verwenden Sie KSP anstelle von KAPT oder Java-Annotation-Processors. Room 3.0 unterstützt weiterhin Java-Quellen als Eingaben.
- Koroutinen zuerst: DAO-Funktionen müssen
suspendFunktionen sein, mit Ausnahme von beobachtbaren Typen.CoroutineContextersetzt Ausführer. - Kein SupportSQLite:
SQLiteDriverAPIs unterstützen Room. Room entferntSupportSQLiteDatabaseaus den Kern-APIs. - API-Änderungen: Migrationen und Datenbank-Callbacks verwenden
SQLiteConnectionanstelle vonSupportSQLiteDatabase. - Konverter für reaktive Typen: Für Rückgabetypen von RxJava, LiveData, Guava und Paging
müssen Sie
@DaoReturnTypeConvertersregistrieren.
Wir empfehlen, die Migration in zwei Phasen durchzuführen: Zuerst bereiten Sie Ihre Codebasis in Room 2.x vor und modernisieren sie, dann wechseln Sie zu Room 3.0.
Vorbereitung und Modernisierung in Room 2.x
Bevor Sie zu Room 3.0 migrieren, können Sie die meisten Modernisierungsarbeiten durchführen, indem Sie auf die aktuelle Room 2.x-Version aktualisieren, z. B. Room 2.8. Room 2.8 unterstützt Kotlin Multiplatform (KMP) und enthält viele Treiber-APIs, die von Room 3.0 verwendet werden.
Auf Room 2.8 und höher aktualisieren
Aktualisieren Sie Ihre Build-Konfiguration, um die aktuelle Room 2.x-Version zu verwenden:
[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" }
Von KAPT zu KSP migrieren
Room 3.0 unterstützt keine Java-Annotation-Processors oder KAPT. Sie müssen Kotlin Symbol Processing (KSP) verwenden. Sie können diese Umstellung vornehmen, während Sie noch Room 2.x verwenden.
Wenden Sie in der Datei
build.gradle.ktsIhres Moduls das KSP-Plug-in an:plugins { id("com.google.devtools.ksp") version "<ksp_version>" }Achten Sie darauf, dass die KSP-Version mit Ihrer Kotlin-Version kompatibel ist.
Ersetzen Sie
kaptoderannotationProcessordurchkspfür die Abhängigkeit des Room-Compilers:dependencies { implementation(libs.androidx.room.runtime) ksp(libs.androidx.room.compiler) }
Koroutinen verwenden
Room 3.0 erfordert Koroutinen für asynchrone Vorgänge.
- Aktualisieren Sie Ihre DAOs: Sofern sie keinen beobachtbaren reaktiven Typ wie
Flowoder RxJava-Typen zurückgeben, müssen alle DAO-Funktionensuspend-Funktionen sein.
// 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>
}
- Wenn Sie Ihre
RoomDatabasemit einem benutzerdefiniertenExecutorfür Datenbankvorgänge konfiguriert haben, migrieren Sie mitsetQueryCoroutineContextim Builder zuCoroutineContext:
Room.databaseBuilder<AppDatabase>(context, "db")
.setQueryCoroutineContext(Dispatchers.IO)
.build()
Treiber-APIs verwenden und Support SQLite vermeiden
Room 3.0 wird vollständig von SQLiteDriver unterstützt und unterstützt SupportSQLiteDatabase nicht mehr in den Kern-APIs.
Wenn Sie setDriver nicht aufrufen, um einen SQLiteDriver für Ihren Datenbank-Builder festzulegen, wird Room 2.8 im Kompatibilitätsmodus ausgeführt, in dem sowohl Support SQLite als auch Treiber-APIs funktionieren. In diesem Kompatibilitätsmodus können Sie Ihre Codebasis schrittweise konvertieren, bevor Sie den Treiber aktivieren.
- Migrationen konvertieren: Migrieren Sie Ihre
MigrationundAutoMigrationSpecUnterklassen, umSQLiteConnectionanstelle vonSupportSQLiteDatabasezu verwenden.
// 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"
)
}
}
- Datenbank-Callbacks konvertieren: Aktualisieren Sie die
RoomDatabase.CallbackImplementierungen, umSQLiteConnectionzu verwenden:
// 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-Funktionen konvertieren: Verwenden Sie für Funktionen, die mit@RawQueryannotiert sind,RoomRawQueryanstelle vonSupportSQLiteQuery:
// Before (SupportSQLiteQuery)
@Dao
interface UserDao {
@RawQuery
fun getUser(query: SupportSQLiteQuery): User
}
// After (RoomRawQuery)
@Dao
interface UserDao {
@RawQuery
suspend fun getUser(query: RoomRawQuery): User
}
Sie können zur Laufzeit eine RoomRawQuery erstellen:
val query = RoomRawQuery(
sql = "SELECT * FROM User WHERE id = ?",
onBindStatement = { statement ->
statement.bindInt(1, userId)
}
)
- Transaktions-APIs konvertieren: Ersetzen Sie die Android-spezifischen Blöcke
withTransactionundrunInTransactiondurchwithWriteTransactionoderwithReadTransaction:
// Before (withTransaction)
db.withTransaction {
// perform database operations
}
// After (withWriteTransaction - Room 2.8)
import androidx.room.withWriteTransaction
db.withWriteTransaction {
// perform database operations
}
Wenn Sie direkten Zugriff auf die Transaktionsverbindung auf niedriger Ebene benötigen, können Sie auch useWriterConnection mit immediateTransaction verwenden.
- Direkte Verwendung von
SupportSQLiteDatabasevermeiden: Wenn Sie umfangreichen Legacy-Code haben, der weiterhinSupportSQLiteDatabaseerfordert und den Sie noch nicht migrieren können, verwenden Sie das Komuserpatibilitätsartefaktandroidx.room:room-sqlite-wrapper:
dependencies {
implementation("androidx.room:room-sqlite-wrapper:$roomVersion")
}
Verwenden Sie dann getSupportWrapper, um eine SupportSQLiteDatabase aus Ihrer Room-Datenbankinstanz abzurufen:
import androidx.room.support.getSupportWrapper
val legacyDb: SupportSQLiteDatabase = roomDatabase.getSupportWrapper()
- SQLite-Treiber festlegen: Nachdem Sie alle Room-API-Verwendungen zu Treiber
APIs migriert haben, konfigurieren Sie einen Treiber wie
BundledSQLiteDriveroderAndroidSQLiteDriver, indem SiesetDriverin IhremRoomDatabaseBuilder aufrufen:
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
val db = Room.databaseBuilder<AppDatabase>(context, "db")
.setDriver(BundledSQLiteDriver())
.build()
Flow-basiertes Tracking von Außerkraftsetzungen verwenden
In Room 2.8 wird die API InvalidationTracker.createFlow eingeführt. Verwenden Sie diese API, um von älteren InvalidationTracker.Observer-Implementierungen zu migrieren, während Sie noch Room 2.x verwenden. So bereiten Sie Ihre Codebasis auf Room 3.0 vor, in dem Observer vollständig entfernt wird.
// 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()
}
Zu Room 3.0 migrieren
Nachdem Sie Ihre Anwendung in Room 2.x modernisiert haben, müssen Sie für die Umstellung auf Room 3.0 Abhängigkeiten, Paketimporte und Datenbank-Callbacks aktualisieren.
Abhängigkeiten und Paketimporte aktualisieren
- Ersetzen Sie in Ihrer Build-Konfiguration
androidx.room-Abhängigkeiten durchandroidx.room3:
[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" }
- Aktualisieren Sie den Block mit den Abhängigkeiten:
dependencies {
implementation(libs.androidx.room3.runtime)
ksp(libs.androidx.room3.compiler)
}
- Aktualisieren Sie Ihre Paketimporte. Ersetzen Sie
import androidx.room.*durchimport androidx.room3.*.
APIs für Typkonverter aktualisieren
In Room 3.0 werden die APIs für Typkonverter umbenannt, um ihre Verwendung für die Konvertierung von Spaltenwerten zu verdeutlichen und Verwechslungen mit den DAO-Rückgabetypkonvertern zu vermeiden.
Aktualisieren Sie die folgenden Annotationen und Funktionen in Ihrer Codebasis:
- Benennen Sie
@TypeConverterin@ColumnTypeConverterum. - Benennen Sie
@TypeConvertersin@ColumnTypeConvertersum. - Benennen Sie
@ProvidedTypeConverterin@ProvidedColumnTypeConverterum. - Benennen Sie
RoomDatabase.Builder.addTypeConverterinaddColumnTypeConverterum.
Beispiel:
// 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()
Callbacks in suspend-Funktionen aktualisieren
In Room 3.0 verwenden Datenbank-Callbacks und Migrationen SQLiteConnection und sind suspend-Funktionen.
- Aktualisieren Sie Ihre manuellen
Migration-Klassen:
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"
)
}
}
- Aktualisieren Sie Ihre
RoomDatabase.Callback-Implementierungen:
val callback = object : RoomDatabase.Callback() {
override suspend fun onCreate(connection: SQLiteConnection) {
// ...
}
}
DAO-Rückgabetypkonverter registrieren
In Room 3.0 müssen Sie für reaktive Rückgabetypen wie RxJava, LiveData, Guava und Paging DAO-Rückgabetypkonverter mit @DaoReturnTypeConverters registrieren.
import androidx.room3.paging.PagingSourceDaoReturnTypeConverter
@Dao
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
interface UserDao {
@Query("SELECT * FROM User")
fun getAllPaginated(): PagingSource<Int, User>
}
- Paging (
PagingSource): Registrieren SiePagingSourceDaoReturnTypeConverteraus demandroidx.room3:room3-pagingArtefakt. - RxJava (
Observable,Flowable,Single,Maybe,Completable) : Registrieren SieRxDaoReturnTypeConvertersaus dem Artefaktandroidx.room3:room3-rxjava3. - Guava (
ListenableFuture): Registrieren SieGuavaDaoReturnTypeConverteraus dem Artefaktandroidx.room3:room3-guava. - LiveData (
LiveData): Registrieren SieLiveDataDaoReturnTypeConverteraus demandroidx.room3:room3-livedataArtefakt.
Entfernung von InvalidationTracker-Observern bestätigen
In Room 3.0 werden InvalidationTracker.Observer und zugehörige Registrierungsmethoden wie addObserver und removeObserver vollständig entfernt.
val userFlow = db.invalidationTracker.createFlow("User").map { _ ->
userDao.getAllUsers()
}