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

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

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

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

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

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

الإعداد

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

Kotlin

dependencies {
    val room_version = "3.0.3"

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

أنيق

dependencies {
    def room_version = "3.0.3"

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

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

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

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

يوفّر فئة قاعدة البيانات لتطبيقك مثيلات من عناصر الوصول إلى البيانات (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
}

ملاحظة: إذا كان تطبيقك يعمل في عملية واحدة، عليك اتّباع نمط تصميم singleton عند إنشاء مثيل لكائن AppDatabase. كل مثيل RoomDatabase مكلف إلى حد ما، ونادرًا ما تحتاج إلى الوصول إلى مثيلات متعددة ضمن عملية واحدة.

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

الاستخدام

بعد تحديد كيان البيانات وكائن الوصول إلى البيانات وكائن قاعدة البيانات، يمكنك استخدام الرمز التالي لإنشاء مثيل لقاعدة البيانات:

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، يمكنك الاطّلاع على المراجع الإضافية التالية:

نماذج