Room, प्रिमिटिव और बॉक्स किए गए टाइप को बदल सकता है. हालांकि, यह इकाइयों के बीच ऑब्जेक्ट रेफ़रंस की अनुमति नहीं देता. टाइप कन्वर्टर इस्तेमाल करने का तरीका जानें. साथ ही, यह भी जानें कि Room, ऑब्जेक्ट रेफ़रंस के साथ काम क्यों नहीं करता.
टाइप कन्वर्टर का इस्तेमाल करना
कभी-कभी, आपको अपने ऐप्लिकेशन में कस्टम डेटा टाइप को किसी एक डेटाबेस कॉलम में सेव करना होता है. टाइप कन्वर्टर उपलब्ध कराकर, कस्टम टाइप इस्तेमाल किए जा सकते हैं. ये ऐसे फ़ंक्शन हैं जो Room को बताते हैं कि कस्टम टाइप को Room के जाने-पहचाने टाइप में कैसे बदला जाए. साथ ही, Room के जाने-पहचाने टाइप को कस्टम टाइप में कैसे बदला जाए. टाइप कन्वर्टर की पहचान करने के लिए, @ColumnTypeConverter एनोटेशन का इस्तेमाल करें.
मान लें कि आपको अपने Room डेटाबेस में Date के इंस्टेंस सेव करने हैं. Room, Date ऑब्जेक्ट को नेटिव तौर पर सेव नहीं कर सकता. इसलिए, आपको टाइप कन्वर्टर तय करने होंगे:
object Converters { @ColumnTypeConverter fun fromTimestamp(value: Long?): Date? { return value?.let { Date(it) } } @ColumnTypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time } }
इस उदाहरण में, दो टाइप कन्वर्टर फ़ंक्शन तय किए गए हैं: एक फ़ंक्शन, Date ऑब्जेक्ट को Long ऑब्जेक्ट में बदलता है. वहीं, दूसरा फ़ंक्शन, Long ऑब्जेक्ट को वापस Date ऑब्जेक्ट में बदलता है. Room, Long ऑब्जेक्ट को सेव कर सकता है. इसलिए, वह इन कन्वर्टर का इस्तेमाल करके Date ऑब्जेक्ट को सेव कर सकता है.
इसके बाद, AppDatabase क्लास में @ColumnTypeConverters एनोटेशन जोड़ें, ताकि Room उस कनवर्टर क्लास का इस्तेमाल कर सके जिसे आपने तय किया है:
@Database(entities = [User::class], version = 1) @ColumnTypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
इन टाइप कन्वर्टर को तय करने के बाद, अपनी इकाइयों और डीएओ में कस्टम टाइप का इस्तेमाल उसी तरह किया जा सकता है जिस तरह प्रिमिटिव टाइप का इस्तेमाल किया जाता है:
@Entity data class User( @PrimaryKey val id: Long, val name: String, val birthday: Date? ) @Dao interface UserDao { @Query("SELECT * FROM user WHERE birthday = :targetDate") suspend fun findUsersBornOnDate(targetDate: Date): List<User> }
इस उदाहरण में, आपने AppDatabase को @ColumnTypeConverters के साथ एनोटेट किया है. इसलिए, Room हर जगह तय किए गए टाइप कन्वर्टर का इस्तेमाल कर सकता है. स्कोप टाइप कन्वर्टर को किसी खास इकाई या डीएओ में बदलने के लिए, अपनी @Entity या @Dao क्लास को @ColumnTypeConverters से एनोटेट करें.
कंट्रोल टाइप कन्वर्टर शुरू करना
आम तौर पर, Room आपके लिए टाइप कन्वर्टर इंस्टैंशिएट करता है. हालाँकि, अगर आपको टाइप कन्वर्टर क्लास में अतिरिक्त डिपेंडेंसी पास करनी हैं, तो आपके ऐप्लिकेशन को सीधे तौर पर उनके इनिशियलाइज़ेशन को कंट्रोल करना होगा. ऐसे में, अपने कनवर्टर क्लास को @ProvidedColumnTypeConverter से एनोटेट करें:
@ProvidedColumnTypeConverter class ExampleConverter { @ColumnTypeConverter fun stringToExample(string: String?): ExampleType? { return string?.let { ExampleType() } } @ColumnTypeConverter fun exampleToString(example: ExampleType?): String? { return example?.toString() } }
@ColumnTypeConverters में अपने कनवर्टर क्लास की जानकारी देने के साथ-साथ, RoomDatabase.Builder.addColumnTypeConverter फ़ंक्शन का इस्तेमाल करके, अपने कनवर्टर क्लास का इंस्टेंस, RoomDatabase बिल्डर को पास करें:
val db = Room.databaseBuilder<MyDatabase>(applicationContext, "database-name") .addColumnTypeConverter(exampleConverterInstance) .build()
जानें कि Room, ऑब्जेक्ट रेफ़रंस की अनुमति क्यों नहीं देता
अहम जानकारी: Room, अलग-अलग एंटिटी क्लास के बीच ऑब्जेक्ट रेफ़रंस की अनुमति नहीं देता. इसके बजाय, आपको उस डेटा का साफ़ तौर पर अनुरोध करना होगा जिसकी आपके ऐप्लिकेशन को ज़रूरत है.
डेटाबेस से ऑब्जेक्ट मॉडल में मैपिंग के संबंध आम तौर पर इस्तेमाल किए जाते हैं. साथ ही, ये सर्वर साइड पर बहुत अच्छी तरह से काम करते हैं. प्रोग्राम के लोड होने पर, प्रॉपर्टी ऐक्सेस की जाती हैं. हालांकि, सर्वर अब भी अच्छी तरह से काम करता है.
हालांकि, क्लाइंट साइड पर इस तरह की लेज़ी लोडिंग मुमकिन नहीं है, क्योंकि यह आम तौर पर यूज़र इंटरफ़ेस (यूआई) थ्रेड पर होती है. साथ ही, यूज़र इंटरफ़ेस (यूआई) थ्रेड में डिस्क पर मौजूद जानकारी को क्वेरी करने से, परफ़ॉर्मेंस से जुड़ी गंभीर समस्याएं पैदा होती हैं. आम तौर पर, यूज़र इंटरफ़ेस (यूआई) थ्रेड को किसी गतिविधि के अपडेट किए गए लेआउट का हिसाब लगाने और उसे बनाने के लिए करीब 16 मि॰से॰ मिलते हैं. इसलिए, भले ही किसी क्वेरी में सिर्फ़ 5 मि॰से॰ लगते हों, फिर भी ऐसा हो सकता है कि आपका ऐप्लिकेशन फ़्रेम बनाने के लिए समय से पहले बंद हो जाए. इससे, विज़ुअल गड़बड़ियां दिख सकती हैं. अगर कोई दूसरा ट्रांजै़क्शन साथ-साथ चल रहा है या डिवाइस पर डिस्क का इस्तेमाल करने वाले अन्य टास्क चल रहे हैं, तो क्वेरी को पूरा होने में और भी समय लग सकता है. हालांकि, लेज़ी लोडिंग का इस्तेमाल न करने पर, आपका ऐप्लिकेशन ज़रूरत से ज़्यादा डेटा फ़ेच करता है. इससे मेमोरी की खपत से जुड़ी समस्याएं होती हैं.
आम तौर पर, ऑब्जेक्ट-रिलेशनल मैपिंग में यह फ़ैसला डेवलपर पर छोड़ दिया जाता है, ताकि वे अपने ऐप्लिकेशन के इस्तेमाल के उदाहरणों के लिए सबसे सही तरीका अपना सकें. डेवलपर आम तौर पर, अपने ऐप्लिकेशन और यूज़र इंटरफ़ेस (यूआई) के बीच मॉडल को शेयर करने का फ़ैसला करते हैं. हालांकि, यह समाधान अच्छी तरह से काम नहीं करता. ऐसा इसलिए, क्योंकि समय के साथ यूज़र इंटरफ़ेस (यूआई) में बदलाव होने पर, शेयर किए गए मॉडल से ऐसी समस्याएं पैदा होती हैं जिनका अनुमान लगाना और डीबग करना डेवलपर के लिए मुश्किल होता है.
उदाहरण के लिए, ऐसे यूज़र इंटरफ़ेस (यूआई) के बारे में सोचें जो Book ऑब्जेक्ट की सूची लोड करता है. इसमें हर किताब का अपना Author ऑब्जेक्ट होता है. शुरुआत में, हो सकता है कि आपने अपनी क्वेरी को इस तरह से डिज़ाइन किया हो कि लेज़ी लोडिंग का इस्तेमाल करके, Book लेखक की जानकारी वापस पा सके. author प्रॉपर्टी को पहली बार फ़ेच करने पर, डेटाबेस से क्वेरी की जाती है. कुछ समय बाद, आपको पता चलता है कि आपको अपने ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में भी लेखक का नाम दिखाना है. इस नाम को ऐक्सेस किया जा सकता है. इसके लिए, यहां दिया गया कोड स्निपेट देखें:
Text(text = book.author.name)
हालांकि, इस बदलाव से Author टेबल को मुख्य थ्रेड पर क्वेरी किया जाता है.
अगर आपने लेखक की जानकारी के लिए पहले से क्वेरी की है, लेकिन आपको इसकी ज़रूरत नहीं है, तो डेटा लोड करने के तरीके में बदलाव करना मुश्किल होता है. उदाहरण के लिए, अगर आपके ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को अब Author जानकारी दिखाने की ज़रूरत नहीं है, तो आपका ऐप्लिकेशन ऐसा डेटा लोड करता है जिसे वह दिखाता नहीं है. इससे मेमोरी की जगह बर्बाद होती है. अगर Author क्लास, Books जैसी किसी दूसरी टेबल को रेफ़रंस देती है, तो आपके ऐप्लिकेशन की परफ़ॉर्मेंस और भी खराब हो जाती है.
Room का इस्तेमाल करके एक साथ कई इकाइयों को रेफ़रंस करने के लिए, एक डेटा ऑब्जेक्ट बनाएँ. इसमें हर इकाई शामिल हो. इसके बाद, एक ऐसी क्वेरी लिखें जो मिलती-जुलती टेबल को जोड़ती हो. यह मॉडल, Room की क्वेरी की पुष्टि करने की मज़बूत सुविधाओं के साथ मिलकर काम करता है. इससे आपका ऐप्लिकेशन, डेटा लोड करते समय कम संसाधनों का इस्तेमाल करता है. इससे आपके ऐप्लिकेशन की परफ़ॉर्मेंस और उपयोगकर्ता अनुभव बेहतर होता है.