ذخیره داده‌ها در یک پایگاه داده محلی با استفاده از Room Part از Android Jetpack .

با کاتلین چند پلتفرمی امتحان کنید
کاتلین چند پلتفرمی امکان اشتراک‌گذاری لایه پایگاه داده با سایر پلتفرم‌ها را فراهم می‌کند. یاد بگیرید چگونه پایگاه داده اتاق را در KMP راه‌اندازی و کار کنید.

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

کتابخانه‌ی پایداری Room یک لایه‌ی انتزاعی روی SQLite فراهم می‌کند تا امکان دسترسی روان به پایگاه داده را فراهم کند و در عین حال از تمام قدرت SQLite بهره ببرد. به طور خاص، Room مزایای زیر را ارائه می‌دهد:

  • تأیید زمان کامپایل کوئری‌های SQL.
  • حاشیه‌نویسی‌های کاربردی که کدهای تکراری و مستعد خطا را به حداقل می‌رسانند.
  • مسیرهای مهاجرت پایگاه داده ساده شده.

ما استفاده از Room را به جای استفاده مستقیم از APIهای SQLite توصیه می‌کنیم.

راه‌اندازی

برای استفاده از Room در برنامه خود، وابستگی‌های زیر را به فایل build.gradle.kts ماژول خود اضافه کنید. Room 3.0 برای پردازش حاشیه‌نویسی به KSP نیاز دارد.

کاتلین

dependencies {
    val room_version = "3.0.1"

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

گرووی

dependencies {
    def room_version = "3.0.1"

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

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

اجزای اولیه

سه جزء اصلی در Room وجود دارد:

  • کلاس پایگاه داده که پایگاه داده را در خود جای داده و به عنوان نقطه دسترسی اصلی برای اتصال اساسی به داده‌های دائمی برنامه شما عمل می‌کند.
  • موجودیت‌های داده‌ای که جداول موجود در پایگاه داده برنامه شما را نشان می‌دهند.
  • اشیاء دسترسی به داده (DAO) که توابعی را ارائه می‌دهند که برنامه شما می‌تواند از آنها برای پرس و جو، به‌روزرسانی، درج و حذف داده‌ها در پایگاه داده استفاده کند.

کلاس پایگاه داده، نمونه‌هایی از DAOهای مرتبط با آن پایگاه داده را در اختیار برنامه شما قرار می‌دهد. در عوض، برنامه می‌تواند از DAOها برای بازیابی داده‌ها از پایگاه داده به عنوان نمونه‌هایی از اشیاء موجودیت داده مرتبط استفاده کند. برنامه همچنین می‌تواند از موجودیت‌های داده تعریف شده برای به‌روزرسانی ردیف‌ها از جداول مربوطه یا ایجاد ردیف‌های جدید برای درج استفاده کند. شکل 1 رابطه بین اجزای مختلف Room را نشان می‌دهد.

شکل ۱. نمودار معماری کتابخانه اتاقی.

پیاده‌سازی نمونه

این بخش، پیاده‌سازی نمونه‌ای از پایگاه داده Room با یک موجودیت داده واحد و یک DAO واحد را ارائه می‌دهد.

موجودیت داده

کد زیر یک موجودیت داده‌ای User تعریف می‌کند. هر نمونه از User نشان‌دهنده یک ردیف در جدول user در پایگاه داده برنامه است.

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String,
    @ColumnInfo(name = "last_name") val lastName: String
)

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

شیء دسترسی به داده (DAO)

کد زیر یک DAO به نام UserDao تعریف می‌کند. UserDao توابعی را ارائه می‌دهد که بقیه برنامه برای تعامل با داده‌های جدول user از آنها استفاده می‌کند.

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    suspend fun loadAllByIds(userIds: IntArray): List<User>

    @Query(
        """
        SELECT * FROM user
        WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1
        """
    )
    suspend fun findByName(first: String, last: String): User

    @Insert
    suspend fun insertAll(vararg users: User)

    @Delete
    suspend fun delete(user: User)
}

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

پایگاه داده

کد زیر یک کلاس AppDatabase برای نگهداری پایگاه داده تعریف می‌کند. AppDatabase پیکربندی پایگاه داده را تعریف می‌کند و به عنوان نقطه دسترسی اصلی برنامه به داده‌های ذخیره شده عمل می‌کند. کلاس پایگاه داده باید شرایط زیر را داشته باشد:

  • این کلاس باید با یک حاشیه‌نویسی @Database که شامل یک آرایه entities است و تمام موجودیت‌های داده مرتبط با پایگاه داده را فهرست می‌کند، حاشیه‌نویسی شود.
  • این کلاس باید یک کلاس انتزاعی باشد که RoomDatabase ارث‌بری می‌کند.
  • برای هر کلاس DAO مرتبط با پایگاه داده، کلاس پایگاه داده باید یک تابع انتزاعی تعریف کند که هیچ آرگومانی دریافت نکند و نمونه‌ای از کلاس DAO را برگرداند.

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

نکته: اگر برنامه شما در یک فرآیند واحد اجرا می‌شود، هنگام نمونه‌سازی یک شیء AppDatabase باید از الگوی طراحی singleton پیروی کنید. هر نمونه RoomDatabase نسبتاً گران است و شما به ندرت نیاز به دسترسی به چندین نمونه در یک فرآیند واحد دارید.

اگر برنامه شما در چندین فرآیند اجرا می‌شود، enableMultiInstanceInvalidation() را در فراخوانی سازنده پایگاه داده خود بگنجانید. به این ترتیب، وقتی در هر فرآیند نمونه‌ای از AppDatabase دارید، می‌توانید فایل پایگاه داده مشترک را در یک فرآیند نامعتبر کنید و این نامعتبر شدن به طور خودکار به نمونه‌های AppDatabase در فرآیندهای دیگر نیز سرایت می‌کند.

کاربرد

پس از تعریف موجودیت داده، DAO و شیء پایگاه داده، می‌توانید از کد زیر برای ایجاد یک نمونه از پایگاه داده استفاده کنید:

val db =
    Room.databaseBuilder<AppDatabase>(applicationContext, "database-name")
        .setDriver(AndroidSQLiteDriver())
        .build()

سپس می‌توانید از توابع انتزاعی AppDatabase برای دریافت یک نمونه از DAO استفاده کنید. در عوض، می‌توانید از توابع نمونه DAO برای تعامل با پایگاه داده استفاده کنید:

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

منابع اضافی

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

نمونه‌ها