रूम का इस्तेमाल करके जटिल डेटा का रेफ़रंस देना

रूम में प्रिमिटिव और बॉक्स वाले टाइप के बीच फ़र्क़ करने की सुविधा मिलती है लेकिन इकाइयों के बीच ऑब्जेक्ट संदर्भ की अनुमति नहीं देता. यह दस्तावेज़ यह बताता है कि टाइप कन्वर्टर का इस्तेमाल कैसे किया जाता है और रूम ऑब्जेक्ट के साथ काम क्यों नहीं करता संदर्भ.

टाइप कन्वर्टर का इस्तेमाल करें

कभी-कभी, आपको कस्टम डेटा टाइप को किसी एक डेटाबेस में सेव करने के लिए, अपने ऐप्लिकेशन की ज़रूरत पड़ती है कॉलम. आप टाइप कन्वर्टर देकर कस्टम टाइप का इस्तेमाल करते हैं, जो ऐसे तरीके जो रूम को, कस्टम टाइप को जाने-पहचाने टाइप में और उन कस्टम टाइप से चैट रूम में बदलाव नहीं किया जा सकता. टाइप कन्वर्टर की पहचान करने के लिए, @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();
}

इन प्रकार के कन्वर्टर के साथ परिभाषित, आप अपने कस्टम प्रकार का इस्तेमाल अपने इकाइयों और डीएओ की तरह ही, प्रिमिटिव टाइप का इस्तेमाल करेंगे:

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 के साथ एनोटेट किया गया. हालांकि, आपके पास यह भी हो सकता है कि आपके @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, जिसमें हर इकाई शामिल है. इसके बाद, ऐसी क्वेरी लिखें जो संबंधित इकाई से जुड़ती हो टेबल. यह बेहतर तरीके से बना मॉडल, रूम की ज़बरदस्त क्वेरी के साथ इस्तेमाल किया जाता है इससे आपके ऐप्लिकेशन को लोड होने के दौरान कम संसाधनों का इस्तेमाल करने की अनुमति मिलती है. डेटा इकट्ठा करने के लिए किया जा सकता है. इससे ऐप्लिकेशन की परफ़ॉर्मेंस और उपयोगकर्ता अनुभव को बेहतर बनाया जा सकता है.