اتاق ۳.۰

کتابخانه‌ی پایداری Room یک لایه‌ی انتزاعی روی SQLite فراهم می‌کند تا دسترسی به پایگاه داده را قوی‌تر کند و در عین حال از تمام قدرت SQLite بهره ببرد.
آخرین به‌روزرسانی انتشار پایدار کاندیدای انتشار انتشار بتا انتشار آلفا
۱۱ مارس ۲۰۲۶ - - - ۳.۰.۰-آلفا۰۱

اعلام وابستگی‌ها

برای افزودن وابستگی به Room3، باید مخزن Google Maven را به پروژه خود اضافه کنید. برای اطلاعات بیشتر، مخزن Maven گوگل را مطالعه کنید.

وابستگی‌های مربوط به مصنوعات مورد نیاز خود را در فایل build.gradle برای برنامه یا ماژول خود اضافه کنید:

کاتلین

dependencies {
    val room_version = ""

    implementation("androidx.room3:room3-runtime:$room_version")
    ksp("androidx.room3:room3-compiler:$room_version")
}

گرووی

dependencies {
    def room_version = ""

    implementation "androidx.room3:room3-runtime:$room_version"

    ksp "androidx.room3:room3-compiler:$room_version"
}

برای اطلاعات بیشتر در مورد استفاده از افزونه KSP، به مستندات شروع سریع KSP مراجعه کنید.

برای اطلاعات بیشتر در مورد وابستگی‌ها، به بخش «افزودن وابستگی‌های ساخت» مراجعه کنید.

از افزونه Room Gradle استفاده کنید

شما می‌توانید از افزونه‌ی Room Gradle برای پیکربندی گزینه‌های کامپایلر Room استفاده کنید. این افزونه پروژه را طوری پیکربندی می‌کند که طرحواره‌های تولید شده (که خروجی وظایف کامپایل هستند و برای مهاجرت‌های خودکار استفاده می‌شوند) به درستی پیکربندی شوند تا دارای ساخت‌های قابل تکرار و قابل ذخیره باشند.

برای افزودن افزونه، در فایل ساخت سطح بالای Gradle خود، افزونه و نسخه آن را تعریف کنید.

گرووی

plugins {
    id 'androidx.room3' version "$room_version" apply false
}

کاتلین

plugins {
    id("androidx.room3") version "$room_version" apply false
}

در فایل ساخت Gradle در سطح ماژول، افزونه را اعمال کنید و از افزونه room3 استفاده کنید.

گرووی

plugins {
    id 'androidx.room3'
}

room3 {
    schemaDirectory "$projectDir/schemas"
}

کاتلین

plugins {
    id("androidx.room3")
}

room3 {
    schemaDirectory("$projectDir/schemas")
}

تنظیم schemaDirectory هنگام استفاده از افزونه Room Gradle الزامی است. این کار کامپایلر Room و وظایف مختلف کامپایل و backend های آن (kotlinc، KSP) را طوری پیکربندی می‌کند که فایل‌های schema را در پوشه‌های flavored، به عنوان مثال schemas/flavorOneDebug/com.package.MyDatabase/1.json خروجی دهد. این فایل‌ها باید در مخزن بررسی شوند تا برای اعتبارسنجی و مهاجرت خودکار استفاده شوند.

بازخورد

بازخورد شما به بهبود Jetpack کمک می‌کند. اگر مشکلات جدیدی کشف کردید یا ایده‌هایی برای بهبود این کتابخانه دارید، به ما اطلاع دهید. لطفاً قبل از ایجاد یک کتابخانه جدید، نگاهی به مشکلات موجود در این کتابخانه بیندازید. می‌توانید با کلیک بر روی دکمه ستاره، رأی خود را به یک مشکل موجود اضافه کنید.

ایجاد یک مسئله جدید

برای اطلاعات بیشتر به مستندات ردیاب مشکل مراجعه کنید.

نسخه ۳.۰

نسخه ۳.۰.۰-آلفا۰۱

۱۱ مارس ۲۰۲۶

androidx.room3:room3-*:3.0.0-alpha01 منتشر شد.

Room 3.0 (بسته androidx.room3 ) یک به‌روزرسانی عمده از بسته Room 2.x ( androidx.room ) است که بر روی Kotlin Multiplatform (KMP) تمرکز دارد.

APIهای حاشیه‌نویسی اصلی به همراه اجزای اصلی به همان شکل نگه داشته می‌شوند:

  • یک کلاس انتزاعی که androidx.room3.RoomDatabase را ارث‌بری می‌کند و با @Database حاشیه‌نویسی شده است، نقطه ورود برای پردازنده حاشیه‌نویسی Room است.
  • اعلان پایگاه داده دارای یک یا چند کلاس داده است که طرح پایگاه داده را توصیف می‌کنند و با @Entity حاشیه‌نویسی شده‌اند.
  • عملیات پایگاه داده در اعلان‌های @Dao تعریف می‌شوند که شامل توابع پرس‌وجو هستند که دستورات SQL آنها از طریق حاشیه‌نویسی @Query تعریف می‌شوند.
  • در زمان اجرا، پیاده‌سازی پایگاه داده را می‌توان از طریق RoomDatabase.Builder که برای پیکربندی پایگاه داده نیز استفاده می‌شود، به دست آورد.

بیشتر مستندات موجود در راهنمای «ذخیره داده‌ها در پایگاه داده محلی با استفاده از Room» هنوز هم مربوط به Room 3.0 هستند.

تفاوت‌های عمده‌ی بین Room 2.x به شرح زیر است:

  • بسته جدید، androidx.room3 .
  • APIهای SupportSQLite دیگر پشتیبانی نمی‌شوند، مگر اینکه از androidx.room3:room3-sqlite-wrapper استفاده کنید.
  • اکنون تمام عملیات پایگاه داده مبتنی بر APIهای Coroutine هستند.
  • فقط تولید کد کاتلین.
  • پردازش نماد کاتلین (KSP) مورد نیاز است.

در کنار تغییرات اساسی، Room 3.0 در مقایسه با 2.x قابلیت‌های جدیدی را به ارمغان می‌آورد:

  • پشتیبانی از JS و WasmJS
  • انواع بازگشتی DAO سفارشی

بسته جدید

برای جلوگیری از مشکلات سازگاری با پیاده‌سازی‌های موجود Room 2.x و برای کتابخانه‌هایی که وابستگی‌های انتقالی به Room دارند (به عنوان مثال، WorkManager)، Room 3.0 در یک بسته جدید قرار می‌گیرد، به این معنی که دارای یک گروه maven جدید و شناسه‌های artifact جدید نیز هست. به عنوان مثال، androidx.room:room-runtime به androidx.room3:room3-runtime تبدیل شده است و کلاس‌هایی مانند androidx.room.RoomDatabase اکنون در androidx.room3.RoomDatabase قرار خواهند گرفت.

بدون پشتیبانی از API های SQLite

Room 3.0 به طور کامل توسط APIهای SQLiteDriver پشتیبانی می‌شود و دیگر به انواع SupportSQLite مانند SupportSQLiteDatabase یا انواع Android مانند Cursor ارجاع نمی‌دهد. این مهمترین تغییر بین Room 3.0 و 2.x است زیرا APIهای RoomDatabase که SupportSQLiteDatabase به همراه API برای دریافت SupportSQLiteOpenHelper منعکس می‌کردند، حذف شده‌اند. اکنون برای ساخت RoomDatabase به SQLiteDriver نیاز است.

برای مثال، APIهای مربوط به عملیات مستقیم پایگاه داده با معادل‌های درایور جایگزین می‌شوند:

// Room 2.x
roomDatabase.runInTransaction { ... }

// Room 3.x
roomDatabase.withWriteTransaction { ... }
// Room 2.x
roomDatabase.query("SELECT * FROM Song").use { cursor -> ... }

// Room 3.x
roomDatabase.useReaderConnection { connection ->
  connection.usePrepared("SELECT * FROM Song") { stmt -> ... }
}

APIهای فراخوانی که به عنوان آرگومان SupportSQLiteDatabase داشتند نیز با API معادل خود که به عنوان آرگومان SQLiteConnection دارد، جایگزین شده‌اند. اینها توابع فراخوانی مهاجرت مانند Migration.onMigrate() و AutoMigrationSpec.onPostMigrate() به همراه فراخوانی‌های پایگاه داده مانند RoomDatabase.Callback.onCreate() ، RoomDatabase.Callback.onOpen() و غیره هستند.

اگر Room در یک پروژه KMP استفاده می‌شد، مهاجرت به نسخه ۳.۰ ساده‌تر بود زیرا بیشتر شامل به‌روزرسانی ارجاعات واردات می‌شد، در غیر این صورت همان استراتژی مهاجرت از Room در نسخه فقط اندروید به KMP اعمال می‌شود، به راهنمای مهاجرت Room KMP مراجعه کنید.

پشتیبانی SQLite Wrapper

Room 3.x برای سهولت در مهاجرت، پوشش SupportSQLite ایجاد شده در نسخه 2.x را حفظ کرده و اکنون در یک مصنوع جدید androidx.room3:room3-sqlite-wrapper قرار دارد. API سازگاری به شما امکان می‌دهد یک RoomDatabase به SupportSQLiteDatabase تبدیل کنید. فراخوانی‌های roomDatabase.openHelper.writableDatabase را می‌توان با roomDatabase.getSupportWrapper() جایگزین کرد.

کاتلین و کوروتین‌ها اول

برای تکامل بهتر کتابخانه، Room 3.0 فقط کد کاتلین تولید می‌کند و فقط یک پردازنده نماد کاتلین (KSP) است. در مقایسه با Room 2.x، تولید کد جاوا وجود ندارد و پیکربندی پردازنده حاشیه‌نویسی از طریق KAPT یا JavaAP دیگر در Room 3.0 امکان‌پذیر نیست. توجه داشته باشید که KSP قادر به پردازش منابع جاوا است و کامپایلر Room برای پایگاه داده، موجودیت‌ها یا DAOهایی که اعلان‌های منبع آنها به زبان جاوا است، کد تولید می‌کند. توصیه می‌شود یک پروژه چند ماژولی داشته باشید که در آن استفاده از Room متمرکز باشد و افزونه Kotlin Gradle و KSP بدون تأثیر بر بقیه کدبیس قابل استفاده باشند.

اتاق ۳.۰ همچنین نیاز به استفاده از Coroutineها دارد، و به طور خاص‌تر، توابع DAO باید در حالت تعلیق باشند، مگر اینکه یک نوع واکنشی مانند Flow یا یک نوع بازگشتی DAO سفارشی را برگردانند. APIهای اتاق برای انجام عملیات پایگاه داده نیز توابع تعلیق هستند، مانند RoomDatabase.useReaderConnection و RoomDatabase.useWriterConnection .

برخلاف Room 2.x، دیگر نمی‌توان RoomDatabase را با یک Executor پیکربندی کرد، در عوض می‌توان یک CoroutineContext به همراه یک dispatcher را از طریق سازنده پایگاه داده ارائه داد.

APIهای InvalidationTracker در Room 3.0 مبتنی بر Flow هستند، InvalidationTracker.Observer به همراه APIهای مرتبط با آن addObserver و removeObserver حذف می‌شوند. مکانیسم واکنش به عملیات پایگاه داده از طریق Coroutine Flowها است که می‌توانند از طریق createFlow() API در InvalidationTracker ایجاد شوند.

مثال استفاده:

fun getArtistTours(from: Date, to: Date): Flow<Map<Artist, TourState>> {
    return db.invalidationTracker.createFlow("Artist").map { _ ->
        val artists = artistsDao.getAllArtists()
        val tours = tourService.fetchStates(artists.map { it.id })
        associateTours(artists, tours, from, to)
    }
}

پشتیبانی وب

نسخه Room 3.0 جاوا اسکریپت و WasmJs را به عنوان هدف KMP اضافه می‌کند. در ترکیب با انتشار رابط‌های SQLiteDriver ( androidx.sqlite:sqlite ) که جاوا اسکریپت و WasmJs را نیز هدف قرار می‌دهند و یک درایور جدید WebWorkerSQLiteDriver که در مصنوع جدید androidx.sqlite:sqlite-web قرار دارد، می‌توان از Room در کد مشترکی استفاده کرد که همه پلتفرم‌های اصلی KMP را هدف قرار می‌دهد.

با توجه به ماهیت ناهمزمان پلتفرم‌های وب، APIهای Room که SQLiteStatement به عنوان آرگومان دریافت می‌کردند، اکنون توابع suspend هستند. نمونه‌هایی از این توابع عبارتند از Migration.onMigrate() ، RoomDatabase.Callback.onCreate() ، PooledConnection.usePrepared() و موارد دیگر. در APIهای درایور، APIهای ناهمزمان در همه پلتفرم‌ها رایج هستند و APIهای همزمان برای اهداف غیر وب رایج هستند. بنابراین، پروژه‌ای که وب را هدف قرار نمی‌دهد، می‌تواند به استفاده از APIهای همزمان ( SQLiteDriver.open() ، SQLiteConnection.prepare() و SQLiteStatement.step() ) در کد مشترک ادامه دهد. در همین حال، پروژه‌ای که فقط وب را هدف قرار می‌دهد، باید از APIهای ناهمزمان ( SQLiteDriver.openAsync() ، SQLiteConnection.prepareAsync() و SQLiteStatement.stepAsync() ) استفاده کند.

برای راحتی، بسته androidx.sqlite توابع افزونه suspend را با نام‌های همزمان APIهای ذکر شده (با اضافه کردن SQLiteConnection.executeSQL ) نیز اضافه کرده است. این APIها زمانی توصیه می‌شوند که پروژه هم پلتفرم‌های وب و هم غیر وب را هدف قرار می‌دهد، زیرا APIها اعلان‌های انتظار/واقعی هستند که نوع مناسب را بر اساس پلتفرم‌ها فراخوانی می‌کنند. اینها استفاده زمان اجرای APIها هستند و استفاده از درایور را در کد مشترک برای همه پلتفرم‌های پشتیبانی شده فعال می‌کنند.

مثال استفاده:

import androidx.sqlite.executeSQL
import androidx.sqlite.step

roomDatabase.useWriterConnection { connection ->
    val deletedSongs = connection.usePrepared(
        "SELECT count(*) FROM Song"
    ) { stmt ->
        stmt.step()
        stmt.getLong(0)
    }
    connection.executeSQL("DELETE FROM Song")
    deletedSongs
}

WebWorkerSQLiteDriver یک پیاده‌سازی از SQLiteDriver است که برای انجام عملیات پایگاه داده خارج از نخ اصلی با یک Web Worker ارتباط برقرار می‌کند و امکان ذخیره پایگاه داده در سیستم فایل خصوصی Origin (OPFS) را فراهم می‌کند. برای نمونه‌سازی درایور، به یک worker که یک پروتکل ارتباطی ساده را پیاده‌سازی می‌کند، نیاز است. این پروتکل در WebWorkerSQLiteDriver KDoc شرح داده شده است.

در حال حاضر WebWorkerSQLiteDriver با یک worker پیش‌فرض که پروتکل ارتباطی را پیاده‌سازی کند، ارائه نمی‌شود، اما به عنوان مثال، کدبیس androidx شامل یک پیاده‌سازی worker است که می‌تواند در پروژه شما استفاده شود. این worker از WASM SQLite استفاده می‌کند و پایگاه داده را در OPFS ذخیره می‌کند. worker نمونه به عنوان یک بسته NPM محلی منتشر می‌شود و به لطف پشتیبانی Kotlin از وابستگی‌های NPM ، می‌توان یک ماژول KMP کوچک برای سرویس‌دهی به worker ایجاد کرد.

پروژه گیت‌هاب زیر را که نحوه استفاده از یک وب ورکر محلی برای Room را نشان می‌دهد، ببینید.

پس از راه‌اندازی یک worker در پروژه، پیکربندی Room for the Web مشابه سایر پلتفرم‌ها است:

fun createDatabase(): MusicDatabase {
    return Room.databaseBuilder<MusicDatabase>("music.db")
        .setDriver(WebWorkerSQLiteDriver(createWorker()))
        .build()
}

fun createWorker() =
    Worker(js("""new URL("sqlite-web-worker/worker.js", import.meta.url)"""))

نسخه آینده درایور وب ممکن است شامل یک worker پیش‌فرض منتشر شده در NPM باشد که راه‌اندازی وب را ساده‌تر می‌کند.

انواع بازگشتی DAO سفارشی

یکپارچه‌سازی‌های مختلف نوع بازگشتی DAO مانند آنهایی که برای RxJava و Paging استفاده می‌شوند، برای استفاده از یک API جدید در Room 3.0 به نام مبدل‌های نوع بازگشتی DAO تغییر یافته‌اند. یک تابع مبدل نوع بازگشتی DAO ( @DaoReturnTypeConverter ) امکان تبدیل نتیجه یک تابع DAO به یک نوع سفارشی تعریف شده توسط تابع حاشیه‌نویسی شده را فراهم می‌کند. این توابع امکان شرکت در کد تولید شده Room را فراهم می‌کنند که نتایج پرس‌وجو را به اشیاء داده تبدیل می‌کند. کلاس‌هایی که حاوی مبدل‌های نوع بازگشتی DAO هستند باید از طریق حاشیه‌نویسی‌های @DaoReturnTypeConverters در اعلان‌های @Database یا @Dao ثبت شوند.

برای مثال، برای اینکه یک کوئری DAO یک PagingSource برگرداند، کلاس مبدل واقع در androidx.room3:room3-paging باید ثبت شود:

@Dao
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
interface MusicDao {
    @Query("SELECT * FROM Song)
    fun getSongsPaginated(): PagingSource<Int, Song>
}

ادغام‌های موجود به مبدل‌های نوع بازگشتی DAO منتقل شده‌اند:

نوع بازگشتی کلاس مبدل مصنوع
منبع صفحه بندی مبدل نوع بازگشتی صفحه‌بندی‌شدهDao androidx.room3:صفحه بندی اتاق3
قابل مشاهده، قابل جریان، قابل تکمیل، منفرد، شاید مبدل‌های نوع بازگشتی RxDao androidx.room3:room3-rxjava3
گوش‌پذیرآینده مبدل نوع بازگشتی GuavaDao androidx.room3:room3-guava
لایو دیتا مبدل نوع بازگشتی LiveDataDao androidx.room3:room3-livedata

مانند مبدل‌های نوع ستون، مبدل‌های نوع بازگشتی DAO می‌توانند توسط برنامه تعریف شوند. برای مثال، یک برنامه می‌تواند یک @DaoReturnTypeConverter را برای نوع وب kotlin.js.Promise اعلان کند.

object PromiseDaoReturnTypeConverter {
    @DaoReturnTypeConverter([OperationType.READ, OperationType.WRITE])
    fun <T> convert(
        db: RoomDatabase,
        executeAndConvert: suspend () -> T
    ): Promise<T> {
        return db.getCoroutineScope().promise { executeAndConvert() }
    }
}

مبدل فوق سپس به توابع پرس و جوی DAO اجازه می‌دهد تا Promise برگردانند:

@Dao
@DaoReturnTypeConverters(PromiseDaoReturnTypeConverter::class)
interface MusicDao {
    @Query("SELECT * FROM Song")
    fun getAllSongs(): Promise<List<Song>>
}

یک تابع @DaoReturnTypeConverter الزاماتی در مورد تعداد پارامترهایی که باید داشته باشد و نوع آنها دارد. پارامترهای ممکن عبارتند از:

  • db: RoomDatabase : (اختیاری) دسترسی به نمونه RoomDatabase را فراهم می‌کند، که می‌تواند برای انجام عملیات اضافی پایگاه داده یا دسترسی به محدوده کوروتین مفید باشد.
  • tableNames: Array<String> : (اختیاری) شامل جداول دسترسی یافته‌ی کوئری است که برای پشتیبانی از انواع observable/reactive هنگام ترکیب با API InvalidationTracker.createFlow() مربوط به Room مفید است.
  • rawQuery: RoomRawQuery : (اختیاری) در زمان اجرا شامل یک نمونه از کوئری است که تبدیل‌هایی مانند استراتژی LIMIT / OFFSET که توسط PagingSourceDaoReturnTypeConverter پیاده‌سازی شده است را فعال می‌کند.
  • executeAndConvert: suspend () -> T : (الزامی) تابع تولید شده توسط Room که کوئری را اجرا کرده و نتیجه آن را به اشیاء داده تجزیه می‌کند.

برای اطلاعات بیشتر در مورد الزامات ایجاد یک مبدل نوع بازگشتی DAO، به KDoc مربوط به API @DaoReturnTypeConverter مراجعه کنید.