রুম ৩.০ হলো একটি প্রধান সংস্করণ আপডেট যা লাইব্রেরিটিকে কোটলিন-ফার্স্ট করে তুলেছে। এটি কোটলিন মাল্টিপ্ল্যাটফর্ম (কেএমপি) সমর্থন করে, কোটলিন সিম্বল প্রসেসিং (কেএসপি) আবশ্যক করে এবং অ্যাসিঙ্ক্রোনাস অপারেশনের জন্য কো-রুটিন ব্যবহার বাধ্যতামূলক করে।
বিদ্যমান Room 2.x অ্যাপ এবং ট্রানজিটিভ ডিপেন্ডেন্সিগুলোর সাথে সামঞ্জস্যের সমস্যা এড়ানোর জন্য, Room 3.0 একটি নতুন প্যাকেজে রাখা হয়েছে: androidx.room3 ।
এই নির্দেশিকায় আপনার বিদ্যমান Room 2.x বাস্তবায়নকে Room 3.0-এ স্থানান্তরিত করার জন্য প্রয়োজনীয় পদক্ষেপগুলো বর্ণনা করা হয়েছে।
রুম ৩.০-এর প্রধান পরিবর্তনসমূহ
মাইগ্রেশন শুরু করার আগে, প্রধান পার্থক্যগুলো জেনে নিন:
- নতুন প্যাকেজ ও আর্টিফ্যাক্ট : সমস্ত ক্লাস
androidx.room3এ থাকে। আর্টিফ্যাক্টগুলোroom3প্রিফিক্স ব্যবহার করে, যেমনandroidx.room3:room3-runtime। - শুধুমাত্র কোটলিন এবং KSP : Room 3.0 জাভা কোড জেনারেশন সমর্থন করে না। KAPT বা জাভা অ্যানোটেশন প্রসেসরের পরিবর্তে KSP ব্যবহার করুন। Room 3.0 এখনও ইনপুট হিসেবে জাভা সোর্স সমর্থন করে।
- প্রথমে কোরাউটিন : অবজার্ভেবল টাইপ ছাড়া, ডিএও (DAO) ফাংশনগুলোকে অবশ্যই
suspendফাংশন হতে হবে।CoroutineContextএক্সিকিউটরের স্থান নেয়। - SupportSQLite নেই : Room-এ
SQLiteDriverAPI ফিরে এসেছে। Room তার কোর API থেকেSupportSQLiteDatabaseসরিয়ে দিয়েছে। - এপিআই পরিবর্তন : মাইগ্রেশন এবং ডাটাবেস কলব্যাকে
SupportSQLiteDatabaseএর পরিবর্তেSQLiteConnectionব্যবহৃত হয়। - রিঅ্যাক্টিভ টাইপের কনভার্টার: RxJava, LiveData, Guava, এবং Paging রিটার্ন টাইপের জন্য আপনাকে
@DaoReturnTypeConvertersরেজিস্টার করতে হবে।
আমরা দুটি স্বতন্ত্র ধাপে মাইগ্রেট করার পরামর্শ দিই: প্রথমে Room 2.x-এ আপনার কোডবেস প্রস্তুত ও আধুনিকীকরণ করা, এবং তারপর Room 3.0-এ স্থানান্তরিত হওয়া।
রুম ২.x প্রস্তুত ও আধুনিকীকরণ করুন।
Room 3.0-এ স্থানান্তরিত হওয়ার আগে, আপনি Room 2.8-এর মতো বর্তমান Room 2.x রিলিজে আপডেট করার মাধ্যমে বেশিরভাগ আধুনিকীকরণের কাজ সম্পন্ন করতে পারেন। Room 2.8 কোটলিন মাল্টিপ্ল্যাটফর্ম বা KMP সমর্থন করে এবং এতে Room 3.0-এর ব্যবহৃত অনেক ড্রাইভার API অন্তর্ভুক্ত রয়েছে।
রুম ২.৮ এবং উচ্চতর রুমে আপগ্রেড করুন।
বর্তমান 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-তে মাইগ্রেট করুন
রুম ৩.০ জাভা অ্যানোটেশন প্রসেসর বা KAPT সমর্থন করে না। আপনাকে অবশ্যই কোটলিন সিম্বল প্রসেসিং (KSP) ব্যবহার করতে হবে। আপনি রুম ২.x-এ থাকা অবস্থাতেই এই পরিবর্তনটি করতে পারেন।
আপনার মডিউলের
build.gradle.ktsফাইলে KSP প্লাগইনটি প্রয়োগ করুন:plugins { id("com.google.devtools.ksp") version "<ksp_version>" }নিশ্চিত করুন যে KSP সংস্করণটি আপনার Kotlin সংস্করণের সাথে সামঞ্জস্যপূর্ণ।
Room কম্পাইলার নির্ভরতার জন্য
kaptবাannotationProcessorপরিবর্তেkspব্যবহার করুন:dependencies { implementation(libs.androidx.room.runtime) ksp(libs.androidx.room.compiler) }
কো-রুটিন গ্রহণ করুন
রুম ৩.০-তে অ্যাসিঙ্ক্রোনাস অপারেশনের জন্য কো-রুটিন প্রয়োজন।
- আপনার 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()
ড্রাইভার এপিআই গ্রহণ করুন এবং SQLite সমর্থন পরিহার করুন।
Room 3.0 সম্পূর্ণরূপে SQLiteDriver দ্বারা সমর্থিত এবং এর কোর API-গুলোতে আর SupportSQLiteDatabase সমর্থন করে না।
আপনার ডাটাবেস বিল্ডারে SQLiteDriver সেট করার জন্য যদি আপনি setDriver কল না করেন, তাহলে Room 2.8 একটি কম্প্যাটিবিলিটি মোডে কাজ করে যেখানে Support SQLite এবং Driver API উভয়ই সক্রিয় থাকে। এই কম্প্যাটিবিলিটি মোড আপনাকে ড্রাইভারটি সক্রিয় করার আগে পর্যায়ক্রমে আপনার কোডবেস রূপান্তর করার সুযোগ দেয়।
- মাইগ্রেশন রূপান্তর করুন : আপনার
MigrationএবংAutoMigrationSpecসাবক্লাসগুলিকেSupportSQLiteDatabaseএর পরিবর্তেSQLiteConnectionব্যবহার করার জন্য মাইগ্রেট করুন।
// 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"
)
}
}
- ডাটাবেস কলব্যাক রূপান্তর করুন :
SQLiteConnectionব্যবহার করার জন্যRoomDatabase.Callbackইমপ্লিমেন্টেশন আপডেট করুন :
// 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 ফাংশন রূপান্তর করুন :@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)
}
)
- ট্রানজ্যাকশন এপিআই রূপান্তর করুন : শুধুমাত্র অ্যান্ড্রয়েডের জন্য
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
}
যদি আপনার ট্রানজ্যাকশন কানেকশনে সরাসরি নিম্ন-স্তরের অ্যাক্সেসের প্রয়োজন হয়, তাহলে আপনি immediateTransaction এর সাথে useWriterConnection ও ব্যবহার করতে পারেন।
-
SupportSQLiteDatabaseএর সরাসরি ব্যবহার পরিহার করুন : যদি আপনার এমন ব্যাপক লিগ্যাসি কোড থাকে যার জন্য এখনওSupportSQLiteDatabaseপ্রয়োজন এবং আপনি এখনও তা মাইগ্রেট করতে পারছেন না,androidx.room:room-sqlite-wrapperকম্প্যাটিবিলিটি আর্টিফ্যাক্টটি ব্যবহার করুন:
dependencies {
implementation("androidx.room:room-sqlite-wrapper:$roomVersion")
}
এবং তারপরে, আপনার Room ডাটাবেস ইনস্ট্যান্স থেকে একটি SupportSQLiteDatabase পেতে getSupportWrapper ব্যবহার করুন:
import androidx.room.support.getSupportWrapper
val legacyDb: SupportSQLiteDatabase = roomDatabase.getSupportWrapper()
- SQLite ড্রাইভার সেট করুন : সমস্ত Room API ব্যবহার ড্রাইভার API-তে স্থানান্তরিত করার পরে, আপনার
RoomDatabaseবিল্ডারেsetDriverকল করেBundledSQLiteDriverবাAndroidSQLiteDriverমতো একটি ড্রাইভার কনফিগার করুন:
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
val db = Room.databaseBuilder<AppDatabase>(context, "db")
.setDriver(BundledSQLiteDriver())
.build()
প্রবাহ-ভিত্তিক অবৈধকরণ ট্র্যাকিং গ্রহণ করুন
রুম ২.৮-এ InvalidationTracker.createFlow API চালু করা হয়েছে। রুম ২.x ব্যবহার করার সময় পুরোনো InvalidationTracker.Observer ইমপ্লিমেন্টেশন থেকে সরে আসতে এই API-টি ব্যবহার করুন। এটি আপনার কোডবেসকে রুম ৩.০-এর জন্য প্রস্তুত করে, যা 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 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.*ব্যবহার করুন।
টাইপ কনভার্টার এপিআই আপডেট করুন
রুম ৩.০ কলামের মান রূপান্তরের ক্ষেত্রে টাইপ কনভার্টার এপিআইগুলোর ব্যবহার স্পষ্ট করার জন্য এবং ডিএও (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()
ফাংশন স্থগিত করতে কলব্যাকগুলি আপডেট করুন
রুম ৩.০-তে, ডাটাবেস কলব্যাক এবং মাইগ্রেশনগুলো 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) {
// ...
}
}
DAO রিটার্ন টাইপ কনভার্টার নিবন্ধন করুন
রুম ৩.০-তে, 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 এবং এর সাথে সম্পর্কিত রেজিস্ট্রেশন মেথডগুলো, যেমন addObserver ও removeObserver , সরিয়ে দেয়।
যদি আপনি প্রথম পর্যায়েই কো-রুটিন ফ্লো-তে স্থানান্তরিত না হয়ে থাকেন, তবে আপনাকে অবশ্যই Observer সমস্ত ব্যবহার createFlow তে মাইগ্রেট করতে হবে:
val userFlow = db.invalidationTracker.createFlow("User").map { _ ->
userDao.getAllUsers()
}