الإشارة إلى البيانات المعقدة باستخدام الغرفة

توفّر غرفة Room وظيفة التحويل بين الأنواع الأولية والمحفوظة في علبة. ولكنّه لا يسمح بمراجع الكائنات بين الكيانات. هذا المستند شرح كيفية استخدام أدوات تحويل الأنواع وسبب عدم توفّر العناصر في الغرفة المراجع.

استخدام أدوات تحويل الأنواع

قد يحتاج تطبيقك أحيانًا إلى تخزين نوع بيانات مخصّص في قاعدة بيانات واحدة. . توفّر الأنواع المخصّصة من خلال توفير أدوات تحويل الأنواع، وهي الطرق التي تحدد للغرفة كيفية تحويل الأنواع المخصصة من الأنواع المعروفة وإليها يمكن أن تظل الغرفة قائمة. ويمكنك تحديد محولات النوع باستخدام التعليق التوضيحي @TypeConverter.

لنفترض أنك تحتاج إلى الاحتفاظ بمثيلات Date في قاعدة بيانات الغرفة. لا تعرف الغرفة كيفية الاحتفاظ بالعناصر Date، لذا ستحتاج إلى لتحديد برامج تحويل النوع:

Kotlin

class Converters {
  @TypeConverter
  fun fromTimestamp(value: Long?): Date? {
    return value?.let { Date(it) }
  }

  @TypeConverter
  fun dateToTimestamp(date: Date?): Long? {
    return date?.time?.toLong()
  }
}

Java

public class Converters {
  @TypeConverter
  public static Date fromTimestamp(Long value) {
    return value == null ? null : new Date(value);
  }

  @TypeConverter
  public static Long dateToTimestamp(Date date) {
    return date == null ? null : date.getTime();
  }
}

يحدّد هذا المثال طريقتَين لتحويل النوع: إحداهما تحوِّل Date. إلى كائن Long، وعنصر آخر ينفذ التحويل العكسي من من Long إلى Date. بما أنّ الغرفة تعرف كيفية الاحتفاظ بكائنات Long، يمكنها استخدام هذه المحوّلات للاحتفاظ بكائنات Date.

بعد ذلك، يمكنك إضافة @TypeConverters تعليق توضيحي لفئة AppDatabase حتى تتعرّف الغرفة على المستخدم الذي أجرى الإحالة الناجحة الفئة التي حددتها:

Kotlin

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

Java

@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
  public abstract UserDao userDao();
}

ومع تحديد أدوات تحويل هذه الأنواع، يمكنك استخدام نوعك المخصص في والكائنات وكائنات DAO تمامًا كما تستخدم الأنواع الأولية:

Kotlin

@Entity
data class User(private val birthday: Date?)

@Dao
interface UserDao {
  @Query("SELECT * FROM user WHERE birthday = :targetDate")
  fun findUsersBornOnDate(targetDate: Date): List<User>
}

Java

@Entity
public class User {
  private Date birthday;
}

@Dao
public interface UserDao {
  @Query("SELECT * FROM user WHERE birthday = :targetDate")
  List<User> findUsersBornOnDate(Date targetDate);
}

في هذا المثال، يمكن للغرفة استخدام محوّل النوع المحدّد في كل مكان لأنك تمت إضافة تعليقات توضيحية إلى AppDatabase باستخدام @TypeConverters. ومع ذلك، يمكنك أيضًا نوع النطاق المستخدمين الذين أجروا إحالات ناجحة إلى كيانات محدّدة أو حِزم DAO من خلال إضافة تعليقات توضيحية إلى @Entity أو @Dao مع @TypeConverters.

إعداد محوّل نوع التحكّم

عادةً ما تعالج الغرفة عادةً مثيل أدوات تحويل الأنواع من أجلك. ومع ذلك، قد تحتاج أحيانًا إلى تمرير تبعيات إضافية إلى محول النوع ما يعني أنّ تطبيقك يحتاج إلى التحكّم في عملية الإعداد مباشرةً من أنواع التحويل الخاصة بك في هذه الحالة، ضع تعليقًا توضيحيًا لفئة المحوّل باستخدام @ProvidedTypeConverter:

Kotlin

@ProvidedTypeConverter
class ExampleConverter {
  @TypeConverter
  fun StringToExample(string: String?): ExampleType? {
    ...
  }

  @TypeConverter
  fun ExampleToString(example: ExampleType?): String? {
    ...
  }
}

Java

@ProvidedTypeConverter
public class ExampleConverter {
  @TypeConverter
  public Example StringToExample(String string) {
    ...
  }

  @TypeConverter
  public String ExampleToString(Example example) {
    ...
  }
}

بعد ذلك، بالإضافة إلى الإعلان عن فئة المستخدمين الذين أجروا إحالة ناجحة في @TypeConverters، استخدِم الـ RoomDatabase.Builder.addTypeConverter() لتمرير مثيل من فئة المحوّل إلى RoomDatabase منصة إنشاء:

Kotlin

val db = Room.databaseBuilder(...)
  .addTypeConverter(exampleConverterInstance)
  .build()

Java

AppDatabase db = Room.databaseBuilder(...)
  .addTypeConverter(exampleConverterInstance)
  .build();

فهم سبب عدم السماح بمراجع العناصر في الغرفة

نصيحة رئيسية: ولا تسمح الغرفة بمراجع العناصر بين فئات الكيانات. بدلاً من ذلك، يجب عليك البيانات التي يحتاجها تطبيقك بشكل صريح.

يعد تعيين العلاقات من قاعدة البيانات إلى نموذج الكائن المعني أمرًا شائعًا يعمل بشكل جيد جدًا على جانب الخادم. حتى عند تحميل البرنامج يبقى أداء الخادم جيدًا.

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

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

على سبيل المثال، يمكنك استخدام واجهة مستخدم تُحمِّل قائمة بكائنات Book مع كل كتاب التي تحتوي على كائن Author. قد تصمم استعلاماتك في البداية لاستخدام طريقة جارٍ التحميل لإتاحة مثيلات Book للمؤلِّف. كانت الاستجابة الأولى يستفسر الحقل author من قاعدة البيانات. في وقت لاحق، تدرك أنك ستعرض أيضًا اسم المؤلف في واجهة المستخدم لتطبيقك. يمكنك الوصول إلى هذه الاسم بسهولة كما هو موضح في مقتطف الرمز التالي:

Kotlin

authorNameTextView.text = book.author.name

Java

authorNameTextView.setText(book.getAuthor().getName());

مع ذلك، يتسبب هذا التغيير الذي يبدو واضحًا في أنّه يتم الاستعلام عن الجدول Author في سلسلة التعليمات الرئيسية

إذا طلبت البحث عن معلومات المؤلف مسبقًا، يصبح من الصعب تغييرها كيفية تحميل البيانات إذا لم تعد بحاجة إلى تلك البيانات. على سبيل المثال، إذا كان تطبيقك لم تعُد واجهة المستخدم بحاجة إلى عرض معلومات Author، ويتم تحميل تطبيقك بفعالية. البيانات التي لم يعد تعرضها، مما يؤدي إلى إهدار مساحة ذاكرة قيّمة. المعلومات عن تطبيقك تنخفض الكفاءة أكثر إذا كانت الفئة Author تشير إلى جدول آخر، مثل Books.

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