इस दस्तावेज़ में बताया गया है कि लागू किए गए मौजूदा रूम को कैसे माइग्रेट किया जाता है जो Kotlin मल्टीप्लैटफ़ॉर्म (KMP) का इस्तेमाल करती है.
किसी मौजूदा Android कोड बेस में, रूम के इस्तेमाल को शेयर किए गए सामान्य केएमपी में माइग्रेट करना मॉड्यूल में इस्तेमाल किए जाने वाले रूम एपीआई के आधार पर कठिनाई का लेवल काफ़ी अलग हो सकता है या कोड बेस पहले से ही कोरूटीन का इस्तेमाल करता है. इस सेक्शन में कुछ दिशा-निर्देश और सलाह दी गई है रूम के इस्तेमाल को सामान्य मॉड्यूल में माइग्रेट करने की कोशिश करते समय.
सबसे पहले, इनके बीच के अंतर और कमियों के बारे में जान लेना ज़रूरी है
रूम के Android वर्शन और KMP वर्शन के बीच की सुविधाएँ
किस तरह इस्तेमाल किया जा सकता है. संक्षेप में, एक सफल माइग्रेशन में रीफ़ैक्टरिंग की ज़रूरत है
SupportSQLite*
एपीआई का इस्तेमाल और उन्हें SQLite ड्राइवर एपीआई से बदलना
साथ ही, मूविंग रूम की जानकारी (@Database
एनोटेट की गई क्लास, डीएओ,
इकाइयों, और इसी तरह के एक जैसे).
जारी रखने से पहले, नीचे दी गई जानकारी को फिर से देखें:
अगले सेक्शन में, कैंपेन को सफल बनाने के लिए ज़रूरी अलग-अलग चरणों के बारे में बताया गया है माइग्रेशन.
SQLite के साथ काम करने वाले टूल से SQLite ड्राइवर पर माइग्रेट करना
androidx.sqlite.db
के एपीआई सिर्फ़ Android पर इस्तेमाल किए जा सकते हैं. इनके लिए किसी भी तरीके का इस्तेमाल करना ज़रूरी है
SQLite ड्राइवर एपीआई की मदद से रीफ़ैक्टरिंग किए गए. पुराने सिस्टम के साथ काम करने की सुविधा के लिए और तब तक
RoomDatabase
को SupportSQLiteOpenHelper.Factory
(यानी कि
कोई SQLiteDriver
सेट नहीं है), तो रूम 'कंपैटबिलिटी मोड' में काम करता है जहां
SQLite और SQLite ड्राइवर के साथ काम करने वाले एपीआई, दोनों उम्मीद के मुताबिक काम करते हैं. यह चालू करता है
ताकि आपको अपने सभी Support SQLite को कन्वर्ट करने की ज़रूरत न पड़े
एक ही बार में SQLite ड्राइवर का इस्तेमाल करता है.
नीचे दिए गए उदाहरण में SQLite और उनके SQLite के सामान्य इस्तेमाल के बारे में बताया गया है ड्राइवर के जैसे:
SQLite के साथ काम करता है (इससे)
बिना किसी नतीजे वाली क्वेरी एक्ज़ीक्यूट करें
val database: SupportSQLiteDatabase = ...
database.execSQL("ALTER TABLE ...")
क्वेरी को एक्ज़ीक्यूट करें, लेकिन उसमें कोई आर्ग्युमेंट न हो
val database: SupportSQLiteDatabase = ...
database.query("SELECT * FROM Pet").use { cursor ->
while (cusor.moveToNext()) {
// read columns
cursor.getInt(0)
cursor.getString(1)
}
}
नतीजे और आर्ग्युमेंट के साथ क्वेरी एक्ज़ीक्यूट करें
database.query("SELECT * FROM Pet WHERE id = ?", id).use { cursor ->
if (cursor.moveToNext()) {
// row found, read columns
} else {
// row not found
}
}
SQLite ड्राइवर (तक)
बिना किसी नतीजे वाली क्वेरी एक्ज़ीक्यूट करें
val connection: SQLiteConnection = ...
connection.execSQL("ALTER TABLE ...")
क्वेरी को एक्ज़ीक्यूट करें, लेकिन उसमें कोई आर्ग्युमेंट न हो
val connection: SQLiteConnection = ...
connection.prepare("SELECT * FROM Pet").use { statement ->
while (statement.step()) {
// read columns
statement.getInt(0)
statement.getText(1)
}
}
नतीजे और आर्ग्युमेंट के साथ क्वेरी एक्ज़ीक्यूट करें
connection.prepare("SELECT * FROM Pet WHERE id = ?").use { statement ->
statement.bindInt(1, id)
if (statement.step()) {
// row found, read columns
} else {
// row not found
}
}
डेटाबेस ट्रांज़ैक्शन एपीआई सीधे SupportSQLiteDatabase
में उपलब्ध हैं, जिनके साथ
beginTransaction()
, setTransactionSuccessful()
, और endTransaction()
.
यह कमरा runInTransaction()
का इस्तेमाल करके, कमरा बुक करने के लिए भी उपलब्ध है. इन्हें माइग्रेट करें
SQLite ड्राइवर एपीआई का इस्तेमाल करता है.
SQLite के साथ काम करता है (इससे)
RoomDatabase
का इस्तेमाल करके लेन-देन करें
val database: RoomDatabase = ...
database.runInTransaction {
// perform database operations in transaction
}
SupportSQLiteDatabase
का इस्तेमाल करके लेन-देन करें
val database: SupportSQLiteDatabase = ...
database.beginTransaction()
try {
// perform database operations in transaction
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
SQLite ड्राइवर (तक)
RoomDatabase
का इस्तेमाल करके लेन-देन करें
val database: RoomDatabase = ...
database.useWriterConnection { transactor ->
transactor.immediateTransaction {
// perform database operations in transaction
}
}
SQLiteConnection
का इस्तेमाल करके लेन-देन करें
val connection: SQLiteConnection = ...
connection.execSQL("BEGIN IMMEDIATE TRANSACTION")
try {
// perform database operations in transaction
connection.execSQL("END TRANSACTION")
} catch(t: Throwable) {
connection.execSQL("ROLLBACK TRANSACTION")
}
कई तरह के कॉलबैक ओवरराइड को भी उनके ड्राइवर वाले वर्शन पर माइग्रेट करने की ज़रूरत होती है:
SQLite के साथ काम करता है (इससे)
माइग्रेशन सब-क्लास
object Migration_1_2 : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
// ...
}
}
अपने-आप होने वाले माइग्रेशन के स्पेसिफ़िकेशन की सब-क्लास
class AutoMigrationSpec_1_2 : AutoMigrationSpec {
override fun onPostMigrate(db: SupportSQLiteDatabase) {
// ...
}
}
डेटाबेस कॉलबैक सब-क्लास
object MyRoomCallback : RoomDatabase.Callback {
override fun onCreate(db: SupportSQLiteDatabase) {
// ...
}
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
// ...
}
override fun onOpen(db: SupportSQLiteDatabase) {
// ...
}
}
SQLite ड्राइवर (तक)
माइग्रेशन सब-क्लास
object Migration_1_2 : Migration(1, 2) {
override fun migrate(connection: SQLiteConnection) {
// ...
}
}
अपने-आप होने वाले माइग्रेशन के स्पेसिफ़िकेशन की सब-क्लास
class AutoMigrationSpec_1_2 : AutoMigrationSpec {
override fun onPostMigrate(connection: SQLiteConnection) {
// ...
}
}
डेटाबेस कॉलबैक सब-क्लास
object MyRoomCallback : RoomDatabase.Callback {
override fun onCreate(connection: SQLiteConnection) {
// ...
}
override fun onDestructiveMigration(connection: SQLiteConnection) {
// ...
}
override fun onOpen(connection: SQLiteConnection) {
// ...
}
}
खास जानकारी देने के लिए, SQLiteDatabase
को SQLiteConnection
से बदलें. ऐसा तब करें, जब
RoomDatabase
उपलब्ध नहीं है, जैसे कि कॉलबैक ओवरराइड (onMigrate
,
onCreate
वगैरह). अगर RoomDatabase
उपलब्ध है, तो इसे ऐक्सेस करें
RoomDatabase.useReaderConnection
और का इस्तेमाल करके डेटाबेस कनेक्शन
के बजाय RoomDatabase.useWriterConnection
RoomDatabase.openHelper.writtableDatabase
.
ब्लॉक करने वाले डीएओ फ़ंक्शन को सस्पेंड फ़ंक्शन में बदलें
रूम का केएमपी वर्शन, I/O करने के लिए कोरूटीन पर निर्भर करता है
कॉन्फ़िगर किए गए CoroutineContext
पर कार्रवाइयां. इसका मतलब है कि
फ़ंक्शन को निलंबित करने के लिए, ब्लॉक करने वाले किसी डीएओ फ़ंक्शन को माइग्रेट करना होगा.
डीएओ फ़ंक्शन को ब्लॉक करना (यहां से)
@Query("SELECT * FROM Todo")
fun getAllTodos(): List<Todo>
डीएओ फ़ंक्शन को निलंबित करना (तक)
@Query("SELECT * FROM Todo")
suspend fun getAllTodos(): List<Todo>
मौजूदा डीएओ ब्लॉक करने वाले फ़ंक्शन को सस्पेंड फ़ंक्शन में माइग्रेट किया जा सकता है यह मुश्किल है, अगर मौजूदा कोड बेस में पहले से कोरूटीन शामिल न हों. कोरूटीन का इस्तेमाल शुरू करने के लिए, Android में कोरूटीन देखें कोड बेस में रहेगा.
रिटर्न के रिस्पॉन्स टाइप को फ़्लो में बदलें
यह ज़रूरी नहीं है कि सभी डीएओ फ़ंक्शन, सस्पेंड फ़ंक्शन हों. वापस आने वाले डीएओ फ़ंक्शन
LiveData
या RxJava के Flowable
जैसे रीऐक्टिव टाइप को कन्वर्ट नहीं किया जाना चाहिए
का इस्तेमाल करें. हालांकि, LiveData
जैसे कुछ टाइप केएमपी नहीं हैं
साथ काम करता है. रिऐक्टिव रिटर्न टाइप वाले डीएओ फ़ंक्शन को
कोरूटीन फ़्लो.
असंगत KMP प्रकार (से)
@Query("SELECT * FROM Todo")
fun getTodosLiveData(): LiveData<List<Todo>>
साथ काम करने वाला केएमपी टाइप (पाने वाले)
@Query("SELECT * FROM Todo")
fun getTodosFlow(): Flow<List<Todo>>
अपने ऐप्लिकेशन में फ़्लो का इस्तेमाल शुरू करने के लिए, Android की नीतियां देखें कोड बेस में एक्सपोर्ट करें.
कोरूटीन कॉन्टेक्स्ट सेट करें (ज़रूरी नहीं)
RoomDatabase
को शेयर किए गए ऐप्लिकेशन के साथ कॉन्फ़िगर किया जा सकता है. हालांकि, ऐसा करना ज़रूरी नहीं है
डेटाबेस करने के लिए RoomDatabase.Builder.setQueryExecutor()
का इस्तेमाल करने वाले एक्ज़िक्यूटर
कार्रवाइयां. प्लान बनाने वाले लोग केएमपी में शामिल नहीं हो सकते, इसलिए रूम की setQueryExecutor()
सामान्य सोर्स के लिए एपीआई उपलब्ध नहीं है. इसके बजाय, RoomDatabase
को यह करना चाहिए
इसे CoroutineContext
के साथ कॉन्फ़िगर किया जाना चाहिए. कॉन्टेक्स्ट सेट करने के लिए
RoomDatabase.Builder.setCoroutineContext()
, अगर कोई भी सेट नहीं है, तो
RoomDatabase
, डिफ़ॉल्ट रूप से Dispatchers.IO
का इस्तेमाल करेगा.
SQLite ड्राइवर सेट करें
जब SQLite के इस्तेमाल से जुड़े फ़ंक्शन को SQLite ड्राइवर एपीआई पर माइग्रेट किया जाता है, तो
ड्राइवर को RoomDatabase.Builder.setDriver
का इस्तेमाल करके कॉन्फ़िगर करना होगा. कॉन्टेंट बनाने
BundledSQLiteDriver
ड्राइवर सुझाया गया है. इनके लिए Driver लागू करना देखें
उपलब्ध ड्राइवर लागू करने के बारे में जानकारी.
कस्टम SupportSQLiteOpenHelper.Factory
को इसका इस्तेमाल करके कॉन्फ़िगर किया गया
RoomDatabase.Builder.openHelperFactory()
केएमपी में काम नहीं करते हैं,
कस्टम ओपन हेल्पर के ज़रिए उपलब्ध कराई गई सुविधाओं को फिर से लागू करना होगा.
SQLite ड्राइवर के इंटरफ़ेस.
कमरे को एक जगह से दूसरी जगह ले जाने से जुड़े एलान
माइग्रेशन के ज़्यादातर चरण पूरे होने के बाद, रूम की जगह बदली जा सकती है
की परिभाषाएं. ध्यान दें कि expect
/ actual
रणनीतियां ये काम कर सकती हैं
का इस्तेमाल रूम से जुड़ी परिभाषाओं को तेज़ी से मूव करने के लिए किया जा सकता है. उदाहरण के लिए, अगर सभी नहीं
ब्लॉक करने वाले डीएओ फ़ंक्शन को सस्पेंड फ़ंक्शन पर माइग्रेट किया जा सकता है, इसलिए
expect
@Dao
की व्याख्या करने वाला ऐसा इंटरफ़ेस बताएं जो कॉमन कोड में खाली हो, लेकिन
में ब्लॉक करने वाले फ़ंक्शन मौजूद हैं.
// shared/src/commonMain/kotlin/Database.kt
@Database(entities = [TodoEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun getDao(): TodoDao
abstract fun getBlockingDao(): BlockingTodoDao
}
@Dao
interface TodoDao {
@Query("SELECT count(*) FROM TodoEntity")
suspend fun count(): Int
}
@Dao
expect interface BlockingTodoDao
// shared/src/androidMain/kotlin/BlockingTodoDao.kt
@Dao
actual interface BlockingTodoDao {
@Query("SELECT count(*) FROM TodoEntity")
fun count(): Int
}