Room 3.0 হল একটি প্রধান ভার্সন আপডেট যা লাইব্রেরিকে Kotlin-ফার্স্ট হিসেবে ট্রানজিশন করে। এটি Kotlin মাল্টিপ্ল্যাটফর্ম (KMP) সাপোর্ট করে, Kotlin সিম্বল প্রসেসিং (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 অ্যানোটেশন প্রসেসরের পরিবর্তে KSP ব্যবহার করুন। Room 3.0 এখনও ইনপুট হিসেবে Java সোর্স সাপোর্ট করে।
- প্রথমে Coroutines: DAO ফাংশন অবশ্যই
suspendফাংশন হতে হবে, তবে অবজার্ভেবল টাইপ এর ব্যতিক্রম।CoroutineContextএক্সিকিউটরদের প্রতিস্থাপন করে। - SupportSQLite নেই:
SQLiteDriverটি API ব্যাক রুম। Room, মূল API থেকেSupportSQLiteDatabaseসরিয়ে দেয়। - API সংক্রান্ত পরিবর্তন: মাইগ্রেশন ও ডেটাবেস কলব্যাক
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-কে সাপোর্ট করে এবং এতে অনেক ড্রাইভার API অন্তর্ভুক্ত আছে যা 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()
ড্রাইভার API গ্রহণ করুন এবং SQLite এড়িয়ে চলুন
Room 3.0 সম্পূর্ণভাবে SQLiteDriver দ্বারা সমর্থিত এবং এর মূল API-তে আর
SupportSQLiteDatabase কাজ করে না।
আপনার ডেটাবেস বিল্ডারে SQLiteDriver সেট করার জন্য setDriver-কে কল না করলে,
Room 2.8 কম্প্যাটিবিলিটি মোডে কাজ করে যেখানে SQLite ও ড্রাইভার
API, দুটিই কাজ করে। এই কম্প্যাটিবিলিটি মোড আপনাকে ড্রাইভার চালু করার আগে আপনার কোডবেসকে
ধাপে ধাপে কনভার্ট করতে দেয়।
- মাইগ্রেশন কনভার্ট করুন:
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"
)
}
}
- ডেটাবেস কলব্যাক কনভার্ট করুন:
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)
}
)
- ট্রানজ্যাকশন API কনভার্ট করা: শুধু Android-এর জন্য
withTransactionএবংrunInTransactionব্লক,useWriterConnectionএবংimmediateTransactionদিয়ে পরিবর্তন করুন:
// Before (withTransaction)
db.withTransaction {
// perform database operations
}
// After (useWriterConnection - Room 2.8)
import androidx.room.useWriterConnection
import androidx.room.immediateTransaction
db.useWriterConnection { connection ->
connection.immediateTransaction {
// perform database operations
}
}
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 ব্যবহার ড্রাইভার API-তে মাইগ্রেট করার পরে,
আপনার
RoomDatabaseবিল্ডারেsetDriverকল করেBundledSQLiteDriverবাAndroidSQLiteDriver-এর মতো ড্রাইভার কনফিগার করুন:
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
val db = Room.databaseBuilder<AppDatabase>(context, "db")
.setDriver(BundledSQLiteDriver())
.build()
ফ্লো-ভিত্তিক ইনভ্যালিডেশন ট্র্যাকিং গ্রহণ করুন
Room 2.8-এ InvalidationTracker.createFlow API চালু করা হয়েছে। এই API ব্যবহার করুন
যাতে Room 2.x-এ থাকাকালীন
পুরনো InvalidationTracker.Observer ইমপ্লিমেন্টেশন থেকে মাইগ্রেট করা যায়। এটি 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.*ব্যবহার করুন।
টাইপ কনভার্টার API আপডেট করুন
Room 3.0-এ টাইপ কনভার্টার API-এর নাম পরিবর্তন করা হয়েছে যাতে কলাম ভ্যালু কনভার্ট করার জন্য সেগুলির ব্যবহার স্পষ্ট করা যায় এবং 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) {
// ...
}
}
DAO রিটার্ন টাইপ কনভার্টার রেজিস্টার করুন
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()
}