حفظ البيانات في قاعدة بيانات محلية باستخدام Room   جزء من Android Jetpack

تجربة Kotlin Multiplatform
تتيح Kotlin Multiplatform مشاركة طبقة قاعدة البيانات مع منصات أخرى. تعرَّف على كيفية إعداد Room Database واستخدامه في KMP

يمكن للتطبيقات التي تعالج كميات كبيرة من البيانات المنظَّمة أن تستفيد بشكل كبير من الاحتفاظ بهذه البيانات محليًا. وأكثر حالات الاستخدام شيوعًا هي تخزين أجزاء البيانات ذات الصلة مؤقتًا، حتى يتمكّن المستخدمون من تصفّح هذا المحتوى عندما يكونون غير متصلين بالإنترنت ولا يمكن للجهاز الوصول إلى الشبكة.

توفر مكتبة Room لاستدامة البيانات طبقة تجريدية فوق SQLite للسماح بالوصول السلس إلى قاعدة البيانات مع الاستفادة من إمكانات SQLite الكاملة. على وجه الخصوص، يوفّر Room المزايا التالية:

  • التحقّق من صحة طلبات البحث بلغة SQL في وقت الترجمة البرمجية
  • التعليقات التوضيحية التي تسهّل الاستخدام وتقلّل من تكرار النصوص النموذجية المعرَّضة للأخطاء
  • مسارات مبسطة لنقل قواعد البيانات

ننصحك باستخدام Room بدلاً من استخدام واجهات برمجة تطبيقات SQLite مباشرةً.

الإعداد

لاستخدام Room في تطبيقك، أضِف التبعيات التالية إلى ملف build.gradle.kts الخاص بالوحدة. يتطلّب Room 3.0 توفُّر KSP لمعالجة التعليقات التوضيحية.

Kotlin

dependencies {
    val room_version = "3.0.0"

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

أنيق

dependencies {
    def room_version = "3.0.0"

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

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

المكوّنات الأساسية

يتضمّن Room ثلاثة مكوّنات رئيسية:

  • فئة قاعدة البيانات التي تحتوي على قاعدة البيانات وتعمل كنقطة الوصول الرئيسية إلى الاتصال الأساسي بالبيانات الثابتة لتطبيقك
  • عناصر البيانات التي تمثّل الجداول في قاعدة بيانات تطبيقك
  • عناصر الوصول إلى البيانات (DAOs) التي توفّر دوال يمكن لتطبيقك استخدامها للاستعلام عن البيانات وتعديلها وإدراجها وحذفها في قاعدة البيانات

يوفر فئة قاعدة البيانات لتطبيقك مثيلات من عناصر الوصول إلى البيانات (DAO) المرتبطة بقاعدة البيانات هذه. وبدورها، يمكن للتطبيق استخدام كائنات الوصول إلى البيانات لاسترداد البيانات من قاعدة البيانات كعناصر من كائنات كيانات البيانات المرتبطة. يمكن للتطبيق أيضًا استخدام كيانات البيانات المحدّدة لتعديل الصفوف من الجداول ذات الصلة أو لإنشاء صفوف جديدة لإدراجها. يوضّح الشكل 1 العلاقة بين المكوّنات المختلفة في Room.

الشكل 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)
}

لمزيد من المعلومات عن كائنات الوصول إلى البيانات، يمكنك الاطّلاع على الوصول إلى البيانات باستخدام كائنات الوصول إلى البيانات في Room.

قاعدة البيانات

يحدّد الرمز التالي فئة AppDatabase لتخزين قاعدة البيانات. يحدّد AppDatabase إعدادات قاعدة البيانات ويعمل كنقطة الوصول الرئيسية للتطبيق إلى البيانات الدائمة. يجب أن يستوفي فئة قاعدة البيانات الشروط التالية:

  • يجب إضافة تعليق توضيحي إلى الفئة باستخدام التعليق التوضيحي @Database الذي يتضمّن مصفوفة entities تسرد جميع عناصر البيانات المرتبطة بقاعدة البيانات.
  • يجب أن يكون الصف صفًا مجرّدًا يمتد إلى RoomDatabase.
  • بالنسبة إلى كل فئة DAO مرتبطة بقاعدة البيانات، يجب أن تحدّد فئة قاعدة البيانات دالة مجرّدة لا تأخذ أي وسيطات وتعرض مثيلاً لفئة DAO.

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

ملاحظة: إذا كان تطبيقك يعمل في عملية واحدة، عليك اتّباع نمط التصميم الفردي عند إنشاء مثيل لكائن AppDatabase. تكون كل نسخة من 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، يُرجى الاطّلاع على المراجع الإضافية التالية:

نماذج