Room 3.0, वर्शन का एक बड़ा अपडेट है. इससे लाइब्रेरी को Kotlin-first में बदल दिया जाता है. यह Kotlin Multiplatform (KMP) के साथ काम करता है. इसके लिए, Kotlin Symbol Processing (KSP) की ज़रूरत होती है. साथ ही, एसिंक्रोनस कार्रवाइयों के लिए कोरूटीन लागू करता है.
Room 2.x के मौजूदा ऐप्लिकेशन और ट्रांज़िटिव डिपेंडेंसी के साथ काम न करने की समस्याओं को रोकने के लिए, Room 3.0 को एक नए पैकेज में रखा गया है: androidx.room3.
इस गाइड में, Room 2.x के मौजूदा वर्शन को Room 3.0 पर माइग्रेट करने का तरीका बताया गया है.
Room 3.0 में हुए मुख्य बदलाव
माइग्रेशन शुरू करने से पहले, इन मुख्य अंतरों के बारे में जान लें:
- नया पैकेज और आर्टफ़ैक्ट: सभी क्लास
androidx.room3में मौजूद होती हैं. आर्टफ़ैक्ट,room3प्रीफ़िक्स का इस्तेमाल करते हैं. जैसे,androidx.room3:room3-runtime. - सिर्फ़ Kotlin और KSP के लिए: Room 3.0, Java कोड जनरेट करने की सुविधा के साथ काम नहीं करता. KAPT या Java annotation processors के बजाय KSP का इस्तेमाल करें. Room 3.0 अब भी Java सोर्स को इनपुट के तौर पर इस्तेमाल करता है.
- कोरूटीन पहले: DAO फ़ंक्शन
suspendफ़ंक्शन होने चाहिए. हालांकि, ऐसा सिर्फ़ ऑब्ज़र्वेबल टाइप के लिए ज़रूरी नहीं है.CoroutineContext, एक्ज़ीक्यूटर की जगह लेता है. - No SupportSQLite:
SQLiteDriverएपीआई, Room के साथ काम नहीं करते. कमरे सेSupportSQLiteDatabaseको मुख्य एपीआई से हटाया गया. - एपीआई में बदलाव: माइग्रेशन और डेटाबेस कॉलबैक,
SupportSQLiteDatabaseके बजायSQLiteConnectionका इस्तेमाल करते हैं. - रिएक्टिव टाइप के लिए कन्वर्टर: RxJava, LiveData, Guava, और Paging
के रिटर्न टाइप के लिए, आपको
@DaoReturnTypeConvertersरजिस्टर करना होगा.
हमारा सुझाव है कि माइग्रेट करने की प्रोसेस को दो चरणों में पूरा करें: पहले चरण में, Room 2.x में अपने कोडबेस को तैयार करें और उसे आधुनिक बनाएं. इसके बाद, दूसरे चरण में Room 3.0 पर स्विच करें.
Room 2.x में तैयारी करना और उसे मॉडर्न बनाना
Room 3.0 पर माइग्रेट करने से पहले, Room 2.x की मौजूदा रिलीज़, जैसे कि Room 2.8 पर अपडेट करके, मॉडर्नाइज़ेशन से जुड़ा ज़्यादातर काम किया जा सकता है. Room 2.8, Kotlin Multiplatform या KMP के साथ काम करता है. इसमें कई ड्राइवर एपीआई शामिल हैं, जिनका इस्तेमाल Room 3.0 करता है.
Room को 2.8 और इसके बाद के वर्शन में अपडेट करें
Room 2.x के मौजूदा वर्शन का इस्तेमाल करने के लिए, अपने बिल्ड कॉन्फ़िगरेशन को अपडेट करें:
[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 से KSP पर माइग्रेट करना
Room 3.0, Java एनोटेशन प्रोसेसर या KAPT के साथ काम नहीं करता. आपको Kotlin Symbol Processing (KSP) का इस्तेमाल करना होगा. Room 2.x का इस्तेमाल करते हुए भी, इस ट्रांज़िशन को किया जा सकता है.
अपने मॉड्यूल के
build.gradle.ktsमें, KSP प्लगिन लागू करें:plugins { id("com.google.devtools.ksp") version "<ksp_version>" }पक्का करें कि KSP का वर्शन, Kotlin के वर्शन के साथ काम करता हो.
रूम कंपाइलर की डिपेंडेंसी के लिए,
kaptयाannotationProcessorकोkspसे बदलें:dependencies { implementation(libs.androidx.room.runtime) ksp(libs.androidx.room.compiler) }
कोरूटीन का इस्तेमाल करना
Room 3.0 में, एसिंक्रोनस ऑपरेशन के लिए कोरूटीन की ज़रूरत होती है.
- अपने DAO अपडेट करें: जब तक वे
Flowया RxJava टाइप जैसे ऑब्ज़र्वेबल रिएक्टिव टाइप नहीं दिखाते, तब तक सभी DAO फ़ंक्शनsuspendफ़ंक्शन होने चाहिए.
// 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>
}
- अगर आपने डेटाबेस से जुड़ी कार्रवाइयां करने के लिए, कस्टम
Executorके साथRoomDatabaseको कॉन्फ़िगर किया है, तो बिल्डर परsetQueryCoroutineContextका इस्तेमाल करके,CoroutineContextपर माइग्रेट करें:
Room.databaseBuilder<AppDatabase>(context, "db")
.setQueryCoroutineContext(Dispatchers.IO)
.build()
ड्राइवर एपीआई का इस्तेमाल करें और Support SQLite से बचें
Room 3.0 को SQLiteDriver का पूरा सपोर्ट मिलता है. साथ ही, यह अपने मुख्य एपीआई में SupportSQLiteDatabase का इस्तेमाल नहीं करता.
अगर आपने अपने डेटाबेस बिल्डर पर SQLiteDriver सेट करने के लिए setDriver को कॉल नहीं किया है, तो
Room 2.8, कंपैटिबिलिटी मोड में काम करता है. इसमें Support SQLite और Driver, दोनों
एपीआई काम करते हैं. इस कंपैटिबिलिटी मोड की मदद से, ड्राइवर को चालू करने से पहले अपने कोडबेस को धीरे-धीरे बदला जा सकता है.
- कन्वर्ज़न माइग्रेशन:
SupportSQLiteDatabaseके बजायSQLiteConnectionका इस्तेमाल करने के लिए, अपनीMigrationऔरAutoMigrationSpecसबक्लास माइग्रेट करें.
// 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"
)
}
}
- डेटाबेस कॉलबैक को बदलना:
RoomDatabase.Callbackको लागू करने के तरीके को अपडेट करकेSQLiteConnectionका इस्तेमाल करें:
// 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) {
// ...
}
}
@RawQueryडीएओ फ़ंक्शन बदलें:@RawQueryके साथ एनोटेट किए गए फ़ंक्शन के लिए,SupportSQLiteQueryके बजायRoomRawQueryका इस्तेमाल करें:
// Before (SupportSQLiteQuery)
@Dao
interface UserDao {
@RawQuery
fun getUser(query: SupportSQLiteQuery): User
}
// After (RoomRawQuery)
@Dao
interface UserDao {
@RawQuery
suspend fun getUser(query: RoomRawQuery): User
}
रनटाइम के दौरान RoomRawQuery बनाया जा सकता है:
val query = RoomRawQuery(
sql = "SELECT * FROM User WHERE id = ?",
onBindStatement = { statement ->
statement.bindInt(1, userId)
}
)
- लेन-देन वाले एपीआई बदलना: Android के लिए उपलब्ध
withTransactionऔरrunInTransactionब्लॉक कोwithWriteTransactionयाwithReadTransactionसे बदलें:
// Before (withTransaction)
db.withTransaction {
// perform database operations
}
// After (withWriteTransaction - Room 2.8)
import androidx.room.withWriteTransaction
db.withWriteTransaction {
// perform database operations
}
अगर आपको लेन-देन के कनेक्शन का सीधे तौर पर लो-लेवल ऐक्सेस चाहिए, तो useWriterConnection के साथ immediateTransaction का इस्तेमाल भी किया जा सकता है.
SupportSQLiteDatabaseका सीधे तौर पर इस्तेमाल करने से बचें: अगर आपके पास ऐसा लेगसी कोड है जिसके लिए अब भीSupportSQLiteDatabaseकी ज़रूरत है और उसे अभी माइग्रेट नहीं किया जा सकता, तोandroidx.room:room-sqlite-wrapperके साथ काम करने वाले आर्टफ़ैक्ट का इस्तेमाल करें:
dependencies {
implementation("androidx.room:room-sqlite-wrapper:$roomVersion")
}
इसके बाद, अपने रूम डेटाबेस इंस्टेंस से SupportSQLiteDatabase पाने के लिए, getSupportWrapper का इस्तेमाल करें:
import androidx.room.support.getSupportWrapper
val legacyDb: SupportSQLiteDatabase = roomDatabase.getSupportWrapper()
- SQLite ड्राइवर सेट करना: Room API के सभी इस्तेमाल को ड्राइवर एपीआई पर माइग्रेट करने के बाद, ड्राइवर को कॉन्फ़िगर करें. जैसे,
BundledSQLiteDriverयाAndroidSQLiteDriver. इसके लिए, अपनेRoomDatabaseबिल्डर मेंsetDriverको कॉल करें:
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
val db = Room.databaseBuilder<AppDatabase>(context, "db")
.setDriver(BundledSQLiteDriver())
.build()
फ़्लो पर आधारित अमान्य होने की ट्रैकिंग को अपनाना
Room 2.8 में InvalidationTracker.createFlow एपीआई उपलब्ध है. Room 2.x पर रहते हुए, InvalidationTracker.Observer के पुराने वर्शन से माइग्रेट करने के लिए, इस एपीआई का इस्तेमाल करें. इससे आपका कोडबेस, Room 3.0 के लिए तैयार हो जाता है. Room 3.0 में, Observer को पूरी तरह से हटा दिया गया है.
// 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 पर माइग्रेट करना
Room 2.x पर अपने ऐप्लिकेशन को मॉडर्न बनाने के बाद, Room 3.0 पर ट्रांज़िशन करने के लिए, आपको डिपेंडेंसी, पैकेज इंपोर्ट, और डेटाबेस कॉलबैक अपडेट करने होंगे.
डिपेंडेंसी और पैकेज इंपोर्ट अपडेट करना
- अपने बिल्ड कॉन्फ़िगरेशन में,
androidx.roomडिपेंडेंसी कोandroidx.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" }
- डिपेंडेंसी ब्लॉक को अपडेट करें:
dependencies {
implementation(libs.androidx.room3.runtime)
ksp(libs.androidx.room3.compiler)
}
- अपने पैकेज इंपोर्ट अपडेट करें.
import androidx.room.*कोimport androidx.room3.*से बदलें.
टाइप कन्वर्टर एपीआई अपडेट करना
Room 3.0, टाइप कन्वर्टर एपीआई के नाम बदलता है, ताकि कॉलम की वैल्यू को बदलने के लिए उनके इस्तेमाल के बारे में साफ़ तौर पर बताया जा सके. साथ ही, DAO के रिटर्न टाइप कन्वर्टर के साथ भ्रम से बचा जा सके.
अपने कोडबेस में, यहां दी गई एनोटेशन और फ़ंक्शन को अपडेट करें:
@TypeConverterका नाम बदलकर@ColumnTypeConverterकरें.@TypeConvertersका नाम बदलकर@ColumnTypeConvertersकरें.@ProvidedTypeConverterका नाम बदलकर@ProvidedColumnTypeConverterकरें.RoomDatabase.Builder.addTypeConverterका नाम बदलकरaddColumnTypeConverterकरें.
उदाहरण:
// 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()
सस्पेंड फ़ंक्शन के लिए अपडेट कॉलबैक
Room 3.0 में, डेटाबेस के कॉलबैक और माइग्रेशन, SQLiteConnection और suspend फ़ंक्शन का इस्तेमाल करते हैं.
- मैन्युअल तरीके से बनाई गई
Migrationक्लास अपडेट करें:
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.Callbackको लागू करने के तरीके अपडेट करें:
val callback = object : RoomDatabase.Callback() {
override suspend fun onCreate(connection: SQLiteConnection) {
// ...
}
}
डीएओ के रिटर्न टाइप कन्वर्टर रजिस्टर करना
Room 3.0 में, RxJava, LiveData, Guava, और Paging जैसे रिएक्टिव रिटर्न टाइप के लिए, आपको @DaoReturnTypeConverters का इस्तेमाल करके DAO रिटर्न टाइप कन्वर्टर रजिस्टर करने होंगे.
import androidx.room3.paging.PagingSourceDaoReturnTypeConverter
@Dao
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
interface UserDao {
@Query("SELECT * FROM User")
fun getAllPaginated(): PagingSource<Int, User>
}
- पेजिंग (
PagingSource):androidx.room3:room3-pagingआर्टफ़ैक्ट सेPagingSourceDaoReturnTypeConverterरजिस्टर करें. - RxJava (
Observable,Flowable,Single,Maybe,Completable):androidx.room3:room3-rxjava3आर्टफ़ैक्ट सेRxDaoReturnTypeConvertersरजिस्टर करें. - Guava (
ListenableFuture):androidx.room3:room3-guavaआर्टफ़ैक्ट सेGuavaDaoReturnTypeConverterरजिस्टर करें. - LiveData (
LiveData):androidx.room3:room3-livedataआर्टफ़ैक्ट सेLiveDataDaoReturnTypeConverterरजिस्टर करें.
InvalidationTracker Observer को हटाने की पुष्टि करना
Room 3.0, InvalidationTracker.Observer और इससे जुड़े रजिस्ट्रेशन के तरीकों को पूरी तरह से हटा देता है. जैसे, addObserver और removeObserver.
अगर आपने पहले चरण में, को-रूटीन फ़्लो पर स्विच नहीं किया है, तो आपको Observer के सभी इस्तेमाल को createFlow पर माइग्रेट करना होगा:
val userFlow = db.invalidationTracker.createFlow("User").map { _ ->
userDao.getAllUsers()
}