حفظ البيانات في قاعدة بيانات محلية باستخدام مكتبة Room وهي جزء من Android Jetpack.
يمكن أن تستفيد التطبيقات التي تعالج كميات كبيرة من البيانات المنظَّمة استفادة كبيرة من الاحتفاظ بهذه البيانات محليًا. حالة الاستخدام الأكثر شيوعًا هي تخزين أجزاء البيانات ذات الصلة مؤقتًا حتى يتمكّن المستخدم من تصفُّح هذا المحتوى في وضع عدم الاتصال بالإنترنت عندما لا يتمكّن الجهاز من الوصول إلى الشبكة.
توفر مكتبة Room لاستدامة البيانات طبقة تجريد فوق SQLite للسماح بالوصول إلى قاعدة البيانات بسلاسة مع الاستفادة من الإمكانات الكاملة لـ SQLite. على وجه الخصوص، توفّر Room المزايا التالية:
- التحقّق من طلبات SQL في وقت التجميع
- التعليقات التوضيحية الملائمة التي تقلّل من الرموز النموذجية المتكررة والمعرَّضة للأخطاء
- مسارات نقل مبسطة لقاعدة البيانات
لهذه الأسباب، ننصحك بشدة باستخدام Room بدلاً من استخدام واجهات برمجة تطبيقات SQLite مباشرةً.
الإعداد
لاستخدام Room في تطبيقك، أضِف التبعيات التالية إلى ملف build.gradle في تطبيقك.
Kotlin
dependencies { val room_version = "2.8.4" implementation("androidx.room:room-runtime:$room_version") // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See Add the KSP plugin to your project ksp("androidx.room:room-compiler:$room_version") // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor("androidx.room:room-compiler:$room_version") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:$room_version") // optional - RxJava2 support for Room implementation("androidx.room:room-rxjava2:$room_version") // optional - RxJava3 support for Room implementation("androidx.room:room-rxjava3:$room_version") // optional - Guava support for Room, including Optional and ListenableFuture implementation("androidx.room:room-guava:$room_version") // optional - Test helpers testImplementation("androidx.room:room-testing:$room_version") // optional - Paging 3 Integration implementation("androidx.room:room-paging:$room_version") }
Groovy
dependencies { def room_version = "2.8.4" implementation "androidx.room:room-runtime:$room_version" // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See KSP Quickstart to add KSP to your build ksp "androidx.room:room-compiler:$room_version" // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration implementation "androidx.room:room-paging:$room_version" }
المكوّنات الأساسية
هناك ثلاثة مكوّنات رئيسية في Room:
- فئة قاعدة البيانات التي تحتوي على قاعدة البيانات وتعمل كنقطة وصول رئيسية للاتصال الأساسي بـ البيانات المحفوظة في تطبيقك.
- كيانات البيانات التي تمثّل الجداول في قاعدة بيانات تطبيقك.
- كائنات الوصول إلى البيانات (DAOs) التي توفّر الطرق التي يمكن لتطبيقك استخدامها لطلب البيانات وتعديلها وإدراجها وحذفها في قاعدة البيانات
توفّر فئة قاعدة البيانات لتطبيقك مثيلات من كائنات الوصول إلى البيانات المرتبطة بقاعدة البيانات هذه. وبالمقابل، يمكن للتطبيق استخدام كائنات الوصول إلى البيانات لاسترداد البيانات من قاعدة البيانات كأمثلة لكائنات كيانات البيانات المرتبطة. يمكن للتطبيق أيضًا استخدام كيانات البيانات المحدّدة لتعديل الصفوف من الجداول المقابلة، أو لإنشاء صفوف جديدة لإدراجها. يوضّح الشكل 1 العلاقة بين المكوّنات المختلفة في Room.
مثال على عملية التنفيذ
يعرض هذا القسم مثالاً على تنفيذ قاعدة بيانات Room تتضمّن كيان بيانات واحدًا وكائن وصول إلى البيانات واحدًا.
كيان البيانات
يعرّف الرمز التالي كيان بيانات User. يمثّل كل مثال من User صفًا في جدول user في قاعدة بيانات التطبيق.
Kotlin
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
Java
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") public String lastName; }
لمزيد من المعلومات عن كيانات البيانات في Room، يُرجى الاطّلاع على تحديد البيانات باستخدام كيانات Room.
كائن الوصول إلى البيانات (DAO)
يعرّف الرمز التالي كائن وصول إلى البيانات يُسمى UserDao. يوفّر UserDao الطرق التي تستخدمها بقية أجزاء التطبيق للتفاعل مع البيانات في جدول user.
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List<User> @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
لمزيد من المعلومات عن كائنات الوصول إلى البيانات، يُرجى الاطّلاع على الوصول إلى البيانات باستخدام كائنات الوصول إلى البيانات في Room.
قاعدة البيانات
يعرّف الرمز التالي فئة AppDatabase للاحتفاظ بقاعدة البيانات.
تحدّد AppDatabase إعدادات قاعدة البيانات وتعمل كنقطة وصول رئيسية للتطبيق إلى البيانات المحفوظة. يجب أن تستوفي فئة قاعدة البيانات الشروط التالية:
- يجب أن تكون الفئة مصنّفة باستخدام تعليق توضيحي
@Databaseيتضمّن مصفوفةentitiesتسرد جميع كيانات البيانات المرتبطة بقاعدة البيانات. - يجب أن تكون الفئة فئة مجرّدة توسّع
RoomDatabase. - لكل فئة من فئات كائنات الوصول إلى البيانات المرتبطة بقاعدة البيانات، يجب أن تحدّد فئة قاعدة البيانات طريقة مجرّدة لا تتضمّن أي وسيطات وتعرض مثالاً على فئة كائن الوصول إلى البيانات.
Kotlin
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
ملاحظة: إذا كان تطبيقك يعمل في عملية واحدة، عليك اتّباع نمط تصميم سينغلتون عند إنشاء مثيل لكائن AppDatabase. كل مثال من RoomDatabase مكلف إلى حد ما، ونادرًا ما تحتاج إلى الوصول إلى أمثلة متعددة ضمن عملية واحدة.
إذا كان تطبيقك يعمل في عمليات متعددة، عليك تضمين
enableMultiInstanceInvalidation() في استدعاء أداة إنشاء قاعدة البيانات. بهذه الطريقة، عندما يكون لديك مثال من AppDatabase
في كل عملية، يمكنك إبطال ملف قاعدة البيانات المشترَك في عملية واحدة،
وينتقل هذا الإبطال تلقائيًا إلى أمثلة
AppDatabase ضمن عمليات أخرى.
الاستخدام
بعد تحديد كيان البيانات وكائن الوصول إلى البيانات وكائن قاعدة البيانات، يمكنك استخدام الرمز التالي لإنشاء مثال على قاعدة البيانات:
Kotlin
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
Java
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
يمكنك بعد ذلك استخدام الطرق المجرّدة من AppDatabase للحصول على مثال من كائن الوصول إلى البيانات. وبالمقابل، يمكنك استخدام الطرق من مثال كائن الوصول إلى البيانات للتفاعل مع قاعدة البيانات:
Kotlin
val userDao = db.userDao() val users: List<User> = userDao.getAll()
Java
UserDao userDao = db.userDao(); List<User> users = userDao.getAll();
مراجع إضافية
لمزيد من المعلومات عن Room، يُرجى الاطّلاع على المراجع الإضافية التالية: