Android Kotlin Fundamentals 06.1: Create a Room database

यह कोडलैब, Android Kotlin Fundamentals कोर्स का हिस्सा है. अगर कोडलैब को क्रम से पूरा किया जाता है, तो आपको इस कोर्स से सबसे ज़्यादा फ़ायदा मिलेगा. कोर्स के सभी कोडलैब, Android Kotlin Fundamentals कोडलैब के लैंडिंग पेज पर दिए गए हैं.

परिचय

ज़्यादातर ऐप्लिकेशन में ऐसा डेटा होता है जिसे उपयोगकर्ता के ऐप्लिकेशन बंद करने के बाद भी सेव रखना होता है. उदाहरण के लिए, ऐप्लिकेशन किसी प्लेलिस्ट, गेम आइटम की इन्वेंट्री, खर्च और आय के रिकॉर्ड, तारामंडलों की कैटलॉग या समय के साथ नींद के डेटा को सेव कर सकता है. आम तौर पर, स्थायी डेटा को सेव करने के लिए डेटाबेस का इस्तेमाल किया जाता है.

Room एक डेटाबेस लाइब्रेरी है, जो Android Jetpack का हिस्सा है. Room डेटाबेस को सेट अप और कॉन्फ़िगर करने से जुड़े कई काम करता है. साथ ही, यह आपके ऐप्लिकेशन को सामान्य फ़ंक्शन कॉल का इस्तेमाल करके डेटाबेस के साथ इंटरैक्ट करने की सुविधा देता है. Room, SQLite डेटाबेस के ऊपर एक ऐब्स्ट्रैक्शन लेयर है. Room की शब्दावली और ज़्यादा मुश्किल क्वेरी के लिए क्वेरी सिंटैक्स, SQLite मॉडल के मुताबिक होता है.

नीचे दी गई इमेज में दिखाया गया है कि इस कोर्स में सुझाए गए पूरे आर्किटेक्चर में Room डेटाबेस कैसे काम करता है.

आपको पहले से क्या पता होना चाहिए

आपको इनके बारे में जानकारी होनी चाहिए:

  • Android ऐप्लिकेशन के लिए बुनियादी यूज़र इंटरफ़ेस (यूआई) बनाना
  • ऐक्टिविटी, फ़्रैगमेंट, और व्यू का इस्तेमाल करके.
  • फ़्रैगमेंट के बीच नेविगेट करना और Safe Args (Gradle प्लगिन) का इस्तेमाल करके, फ़्रैगमेंट के बीच डेटा पास करना.
  • मॉडल, व्यू-मॉडल फ़ैक्ट्रियां, और LiveData और इसके ऑब्ज़र्वर देखें. आर्किटेक्चर कॉम्पोनेंट के इन विषयों को इस कोर्स के पिछले कोडलैब में शामिल किया गया है.
  • एसक्यूएल डेटाबेस और SQLite लैंग्वेज की बुनियादी जानकारी. खास जानकारी या रीफ़्रेशर के लिए, SQLite Primer देखें.

आपको क्या सीखने को मिलेगा

  • डेटा को सेव करने के लिए, Room डेटाबेस बनाने और उससे इंटरैक्ट करने का तरीका.
  • डेटाबेस में टेबल तय करने वाली डेटा क्लास बनाने का तरीका.
  • Kotlin फ़ंक्शन को SQL क्वेरी से मैप करने के लिए, डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) का इस्तेमाल कैसे करें.
  • यह जांच करने का तरीका कि आपका डेटाबेस काम कर रहा है या नहीं.

आपको क्या करना होगा

  • रात की नींद से जुड़े डेटा के लिए इंटरफ़ेस वाला Room डेटाबेस बनाएं.
  • दिए गए टेस्ट का इस्तेमाल करके डेटाबेस की जांच करें.

इस कोडलैब में, आपको नींद की क्वालिटी को ट्रैक करने वाले ऐप्लिकेशन का डेटाबेस वाला हिस्सा बनाने का तरीका बताया गया है. यह ऐप्लिकेशन, समय के साथ नींद के डेटा को सेव करने के लिए डेटाबेस का इस्तेमाल करता है.

ऐप्लिकेशन में दो स्क्रीन हैं, जिन्हें फ़्रैगमेंट के तौर पर दिखाया गया है. इनके बारे में यहां दी गई इमेज में बताया गया है.

बाईं ओर दिखाई गई पहली स्क्रीन में, ट्रैकिंग शुरू और बंद करने के बटन हैं. स्क्रीन पर, उपयोगकर्ता का नींद से जुड़ा सारा डेटा दिखता है. मिटाएं बटन दबाने पर, ऐप्लिकेशन ने उपयोगकर्ता के लिए जो भी डेटा इकट्ठा किया है वह हमेशा के लिए मिट जाता है.

दाईं ओर दिखाई गई दूसरी स्क्रीन, नींद की क्वालिटी की रेटिंग चुनने के लिए है. ऐप्लिकेशन में, रेटिंग को संख्या के तौर पर दिखाया जाता है. डेवलपमेंट के लिए, ऐप्लिकेशन में चेहरे के आइकॉन और उनके संख्यात्मक मान, दोनों दिखाए जाते हैं.

उपयोगकर्ता का फ़्लो इस तरह होता है:

  • उपयोगकर्ता ऐप्लिकेशन खोलता है और उसे नींद को ट्रैक करने वाली स्क्रीन दिखती है.
  • उपयोगकर्ता, शुरू करें बटन पर टैप करता है. यह कुकी, वीडियो शुरू होने का समय रिकॉर्ड करती है और उसे दिखाती है. शुरू करें बटन बंद हो जाता है और बंद करें बटन चालू हो जाता है.
  • उपयोगकर्ता बंद करें बटन पर टैप करता है. यह नींद के खत्म होने का समय रिकॉर्ड करता है और नींद की क्वालिटी वाली स्क्रीन खोलता है.
  • उपयोगकर्ता, नींद की क्वालिटी का आइकॉन चुनता है. स्क्रीन बंद हो जाती है. इसके बाद, ट्रैकिंग स्क्रीन पर नींद खत्म होने का समय और नींद की क्वालिटी दिखती है. बंद करें बटन बंद है और शुरू करें बटन चालू है. यह ऐप्लिकेशन, अगली रात के लिए तैयार है.
  • डेटाबेस में डेटा मौजूद होने पर, हटाएं बटन चालू हो जाता है. जब उपयोगकर्ता मिटाएं बटन पर टैप करता है, तो उसका पूरा डेटा मिट जाता है. इसके लिए, उससे कोई पुष्टि नहीं की जाती. जैसे, "क्या आपको पक्का मिटाना है?" मैसेज नहीं दिखता.

यह ऐप्लिकेशन, आसान आर्किटेक्चर का इस्तेमाल करता है. यहां पूरे आर्किटेक्चर के कॉन्टेक्स्ट में इसे दिखाया गया है. ऐप्लिकेशन सिर्फ़ इन कॉम्पोनेंट का इस्तेमाल करता है:

  • यूज़र इंटरफ़ेस (यूआई) कंट्रोलर
  • मॉडल और LiveData देखें
  • रूम डेटाबेस

पहला चरण: स्टार्टर ऐप्लिकेशन डाउनलोड और रन करना

  1. GitHub से TrackMySleepQuality-Starter ऐप्लिकेशन डाउनलोड करें.
  2. ऐप्लिकेशन बनाएं और उसे चलाएं. ऐप्लिकेशन में SleepTrackerFragment फ़्रैगमेंट के लिए यूज़र इंटरफ़ेस (यूआई) दिखता है, लेकिन कोई डेटा नहीं दिखता. बटन टैप करने पर काम नहीं करते.

दूसरा चरण: स्टार्टर ऐप्लिकेशन की जांच करना

  1. Gradle फ़ाइलों पर एक नज़र डालें:
  • प्रोजेक्ट की Gradle फ़ाइल
    प्रोजेक्ट-लेवल की build.gradle फ़ाइल में, उन वैरिएबल पर ध्यान दें जो लाइब्रेरी के वर्शन तय करते हैं. स्टार्टर ऐप्लिकेशन में इस्तेमाल किए गए वर्शन, एक साथ अच्छी तरह से काम करते हैं. साथ ही, वे इस ऐप्लिकेशन के साथ भी अच्छी तरह से काम करते हैं. इस कोडलैब को पूरा करने तक, Android Studio आपको कुछ वर्शन अपडेट करने के लिए कह सकता है. यह आप पर निर्भर करता है कि आपको अपडेट करना है या ऐप्लिकेशन में मौजूद वर्शन का इस्तेमाल जारी रखना है. अगर आपको कंपाइल करने से जुड़ी "अजीब" गड़बड़ियां मिलती हैं, तो लाइब्रेरी के उन वर्शन के कॉम्बिनेशन का इस्तेमाल करें जिनका इस्तेमाल फ़ाइनल सलूशन ऐप्लिकेशन करता है.
  • मॉड्यूल की Gradle फ़ाइल. सभी Android Jetpack लाइब्रेरी के लिए दी गई डिपेंडेंसी पर ध्यान दें. इनमें Room और कोरूटीन के लिए डिपेंडेंसी शामिल हैं.
  1. पैकेज और यूज़र इंटरफ़ेस देखें. ऐप्लिकेशन को उसकी सुविधाओं के हिसाब से व्यवस्थित किया गया है. इस पैकेज में प्लेसहोल्डर फ़ाइलें होती हैं. इनमें आपको कोडलैब की इस सीरीज़ के दौरान कोड जोड़ना होगा.
  • Room डेटाबेस से जुड़े सभी कोड के लिए, database पैकेज.
  • sleepquality और sleeptracker पैकेज में, हर स्क्रीन के लिए फ़्रैगमेंट, व्यू मॉडल, और व्यू मॉडल फ़ैक्ट्री शामिल होती है.
  1. Util.kt फ़ाइल देखें. इसमें ऐसे फ़ंक्शन शामिल हैं जिनकी मदद से, नींद की क्वालिटी का डेटा दिखाया जा सकता है. कुछ कोड पर टिप्पणी की गई है, क्योंकि यह एक ऐसे व्यू मॉडल को रेफ़रंस करता है जिसे आपको बाद में बनाना है.
  2. androidTest फ़ोल्डर (SleepDatabaseTest.kt) देखें. इस टेस्ट का इस्तेमाल यह पुष्टि करने के लिए किया जाएगा कि डेटाबेस उम्मीद के मुताबिक काम कर रहा है या नहीं.

Android में, डेटा को डेटा क्लास में दिखाया जाता है. साथ ही, फ़ंक्शन कॉल का इस्तेमाल करके डेटा को ऐक्सेस और उसमें बदलाव किया जाता है. हालांकि, डेटाबेस की दुनिया में आपको इकाइयों और क्वेरी की ज़रूरत होती है.

  • इकाई, किसी ऑब्जेक्ट या कॉन्सेप्ट और उसकी प्रॉपर्टी को डेटाबेस में सेव करने के लिए इस्तेमाल की जाती है. इकाई क्लास, टेबल को तय करती है. साथ ही, उस क्लास का हर इंस्टेंस, टेबल में मौजूद एक लाइन को दिखाता है. हर प्रॉपर्टी, एक कॉलम तय करती है. आपके ऐप्लिकेशन में, यह इकाई एक रात की नींद के बारे में जानकारी सेव करेगी.
  • क्वेरी, किसी डेटाबेस टेबल या टेबल के कॉम्बिनेशन से डेटा या जानकारी पाने का अनुरोध होती है. इसके अलावा, यह डेटा पर कोई कार्रवाई करने का अनुरोध भी हो सकती है. सामान्य क्वेरी, इकाइयों को पाने, डालने, और अपडेट करने के लिए होती हैं. उदाहरण के लिए, रिकॉर्ड की गई सभी रातों की नींद के बारे में क्वेरी की जा सकती है. इन्हें शुरू होने के समय के हिसाब से क्रम में लगाया जा सकता है.

Room आपके लिए, Kotlin डेटा क्लास से ऐसी इकाइयां बनाने का काम करता है जिन्हें SQLite टेबल में सेव किया जा सकता है. साथ ही, यह फ़ंक्शन के एलान से SQL क्वेरी बनाने का काम भी करता है.

आपको हर इकाई को एनोटेट की गई डेटा क्लास के तौर पर और इंटरैक्शन को एनोटेट किए गए इंटरफ़ेस, डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) के तौर पर तय करना होगा. Room इन एनोटेट की गई क्लास का इस्तेमाल करके, डेटाबेस में टेबल बनाता है. साथ ही, डेटाबेस पर काम करने वाली क्वेरी बनाता है.

पहला चरण: SleepNight इकाई बनाना

इस टास्क में, आपको एक रात की नींद को एनोटेट की गई डेटा क्लास के तौर पर तय करना है.

एक रात की नींद का डेटा रिकॉर्ड करने के लिए, आपको नींद शुरू होने का समय, नींद खत्म होने का समय, और नींद की क्वालिटी की रेटिंग देनी होगी.

साथ ही, रात की पहचान करने के लिए आपके पास एक आईडी होना चाहिए.

  1. database पैकेज में, SleepNight.kt फ़ाइल ढूंढें और खोलें.
  2. आईडी, शुरू होने का समय (मिलीसेकंड में), खत्म होने का समय (मिलीसेकंड में), और नींद की क्वालिटी की संख्या के हिसाब से रेटिंग के पैरामीटर के साथ SleepNight डेटा क्लास बनाएं.
  • आपको sleepQuality को शुरू करना होगा. इसलिए, इसे -1 पर सेट करें. इससे पता चलता है कि कोई क्वालिटी डेटा इकट्ठा नहीं किया गया है.
  • आपको खत्म होने का समय भी सेट करना होगा. इसे शुरू होने के समय पर सेट करें, ताकि यह पता चल सके कि खत्म होने का समय अब तक रिकॉर्ड नहीं किया गया है.
data class SleepNight(
       var nightId: Long = 0L,
       val startTimeMilli: Long = System.currentTimeMillis(),
       var endTimeMilli: Long = startTimeMilli,
       var sleepQuality: Int = -1
)
  1. क्लास के एलान से पहले, डेटा क्लास को @Entity के साथ एनोटेट करें. टेबल को नाम दें daily_sleep_quality_table. tableName के लिए आर्ग्युमेंट देना ज़रूरी नहीं है, लेकिन इसका सुझाव दिया जाता है. दस्तावेज़ में अन्य तर्कों के बारे में जानकारी दी गई है.

    अगर कहा जाए, तो androidx लाइब्रेरी से Entity और अन्य सभी एनोटेशन इंपोर्ट करें.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)
  1. nightId को प्राइमरी कुंजी के तौर पर पहचानने के लिए, nightId प्रॉपर्टी को @PrimaryKey के साथ एनोटेट करें. पैरामीटर autoGenerate को true पर सेट करें, ताकि Room हर इकाई के लिए आईडी जनरेट कर सके. इससे यह पक्का होता है कि हर रात के लिए आईडी यूनीक है.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...
  1. @ColumnInfo का इस्तेमाल करके, बाकी प्रॉपर्टी के बारे में जानकारी दें. नीचे दिखाए गए तरीके से, पैरामीटर का इस्तेमाल करके प्रॉपर्टी के नाम पसंद के मुताबिक बनाएं.
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
       @PrimaryKey(autoGenerate = true)
       var nightId: Long = 0L,

       @ColumnInfo(name = "start_time_milli")
       val startTimeMilli: Long = System.currentTimeMillis(),

       @ColumnInfo(name = "end_time_milli")
       var endTimeMilli: Long = startTimeMilli,

       @ColumnInfo(name = "quality_rating")
       var sleepQuality: Int = -1
)
  1. अपने कोड को बनाएं और चलाकर देखें, ताकि यह पक्का किया जा सके कि उसमें कोई गड़बड़ी नहीं है.

इस टास्क में, आपको डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) तय करना होगा. Android पर, डीएओ डेटाबेस में डेटा डालने, मिटाने, और अपडेट करने के लिए आसान तरीके उपलब्ध कराता है.

Room डेटाबेस का इस्तेमाल करते समय, अपने कोड में Kotlin फ़ंक्शन तय करके और उन्हें कॉल करके डेटाबेस को क्वेरी किया जाता है. ये Kotlin फ़ंक्शन, एसक्यूएल क्वेरी के साथ मैप किए जाते हैं. एनोटेशन का इस्तेमाल करके, DAO में उन मैपिंग को तय किया जाता है. इसके बाद, Room ज़रूरी कोड बनाता है.

डीएओ को अपने डेटाबेस को ऐक्सेस करने के लिए कस्टम इंटरफ़ेस तय करने के तौर पर देखा जा सकता है.

डेटाबेस से जुड़ी सामान्य कार्रवाइयों के लिए, Room लाइब्रेरी में @Insert, @Delete, और @Update जैसे एनोटेशन उपलब्ध होते हैं. बाकी सभी के लिए, @Query एनोटेशन उपलब्ध है. SQLite के साथ काम करने वाली कोई भी क्वेरी लिखी जा सकती है.

एक और फ़ायदे के तौर पर, Android Studio में क्वेरी बनाते समय कंपाइलर, सिंटैक्स से जुड़ी गड़बड़ियों के लिए आपकी एसक्यूएल क्वेरी की जांच करता है.

नींद ट्रैक करने वाले डेटाबेस में, रात में सोने की जानकारी के लिए, आपको ये काम करने होंगे:

  • नई रातें जोड़ें.
  • अपडेट करें पर क्लिक करके, किसी मौजूदा रात की नींद के खत्म होने का समय और क्वालिटी रेटिंग अपडेट करें.
  • कुंजी के आधार पर, किसी खास रात की जानकारी पाएं.
  • सभी रातों के लिए उपलब्ध कमरे की जानकारी पाएं, ताकि उन्हें दिखाया जा सके.
  • सबसे हाल की रात की फ़ोटो दिखाओ.
  • डेटाबेस में मौजूद सभी एंट्री मिटाएं.

पहला चरण: SleepDatabase DAO बनाना

  1. database पैकेज में, SleepDatabaseDao.kt खोलें.
  2. ध्यान दें कि interface SleepDatabaseDao को @Dao के साथ एनोटेट किया गया है. सभी DAO को @Dao कीवर्ड के साथ एनोटेट करना ज़रूरी है.
@Dao
interface SleepDatabaseDao {}
  1. इंटरफ़ेस के मुख्य हिस्से में, @Insert एनोटेशन जोड़ें. @Insert के नीचे, एक insert() फ़ंक्शन जोड़ें. यह Entity क्लास SleepNight के इंस्टेंस को अपने तर्क के तौर पर लेता है.

    बस इतना ही. Room, डेटाबेस में SleepNight डालने के लिए ज़रूरी कोड जनरेट करेगा. जब Kotlin कोड से insert() को कॉल किया जाता है, तब Room, SQL क्वेरी को एक्ज़ीक्यूट करता है, ताकि इकाई को डेटाबेस में डाला जा सके. (ध्यान दें: फ़ंक्शन को अपनी पसंद के मुताबिक कोई भी नाम दिया जा सकता है.)
@Insert
fun insert(night: SleepNight)
  1. एक SleepNight के लिए, update() फ़ंक्शन के साथ @Update एनोटेशन जोड़ें. अपडेट की गई इकाई वही होती है जिसकी कुंजी, पास की गई इकाई की कुंजी से मेल खाती है. आपके पास इकाई की कुछ या सभी अन्य प्रॉपर्टी अपडेट करने का विकल्प होता है.
@Update
fun update(night: SleepNight)

बची हुई सुविधा के लिए, कोई सुविधा एनोटेशन नहीं है. इसलिए, आपको @Query एनोटेशन का इस्तेमाल करना होगा और SQLite क्वेरी देनी होंगी.

  1. @Query एनोटेशन जोड़ें. इसमें get() फ़ंक्शन का इस्तेमाल करें. यह Long key आर्ग्युमेंट लेता है और नल हो सकने वाला SleepNight दिखाता है. आपको किसी पैरामीटर के मौजूद न होने पर गड़बड़ी दिखेगी.
@Query
fun get(key: Long): SleepNight?
  1. क्वेरी को एनोटेशन में स्ट्रिंग पैरामीटर के तौर पर दिया जाता है. @Query में कोई पैरामीटर जोड़ें. इसे String बनाएं, जो SQLite क्वेरी हो.
  • daily_sleep_quality_table से सभी कॉलम चुनें
  • WHERE में मौजूद nightId, :key आर्ग्युमेंट से मेल खाता है.

    :key पर ध्यान दें. फ़ंक्शन में आर्ग्युमेंट का रेफ़रंस देने के लिए, क्वेरी में कोलन नोटेशन का इस्तेमाल किया जाता है.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
  1. daily_sleep_quality_table से DELETE करने के लिए, clear() फ़ंक्शन और SQLite क्वेरी के साथ एक और @Query जोड़ें. इस क्वेरी से टेबल नहीं मिटती.

    @Delete एनोटेशन से एक आइटम मिटाया जाता है. हालांकि, @Delete का इस्तेमाल करके, मिटाने के लिए रातों की सूची दी जा सकती है. इसकी कमी यह है कि आपको टेबल में मौजूद डेटा को फ़ेच करना होगा या उसके बारे में जानना होगा. @Delete एनोटेशन, किसी खास एंट्री को मिटाने के लिए बहुत अच्छा है. हालांकि, यह किसी टेबल से सभी एंट्री मिटाने के लिए कारगर नहीं है.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
  1. getTonight() फ़ंक्शन का इस्तेमाल करके, @Query जोड़ें. getTonight() से मिले SleepNight को नल वैल्यू असाइन करने की अनुमति दें, ताकि फ़ंक्शन उस स्थिति को हैंडल कर सके जब टेबल खाली हो. (शुरुआत में टेबल खाली है. डेटा मिटाने के बाद भी टेबल खाली है.)

    डेटाबेस से "आज रात" पाने के लिए, एक SQLite क्वेरी लिखें. यह क्वेरी, नतीजों की सूची का पहला एलिमेंट दिखाती है. इस सूची को nightId के हिसाब से घटते क्रम में लगाया गया है. सिर्फ़ एक एलिमेंट दिखाने के लिए, LIMIT 1 का इस्तेमाल करें.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
  1. getAllNights() फ़ंक्शन के साथ @Query जोड़ना:
  • SQLite क्वेरी से, daily_sleep_quality_table के सभी कॉलम को घटते क्रम में दिखाएं.
  • getAllNights() को SleepNight इकाइयों की सूची को LiveData के तौर पर दिखाने के लिए कहें. Room इस LiveData को आपके लिए अपडेट करता रहता है. इसका मतलब है कि आपको सिर्फ़ एक बार डेटा लेना होगा.
  • इसके लिए, आपको androidx.lifecycle.LiveData से LiveData इंपोर्ट करना पड़ सकता है.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
  1. आपको कोई बदलाव नहीं दिखेगा. हालांकि, अपने ऐप्लिकेशन को चलाकर देखें, ताकि यह पक्का किया जा सके कि उसमें कोई गड़बड़ी नहीं है.

इस टास्क में, आपको एक Room डेटाबेस बनाना है. यह डेटाबेस, पिछले टास्क में बनाए गए Entity और डीएओ का इस्तेमाल करता है.

आपको @Database के साथ एनोटेट की गई ऐब्स्ट्रैक्ट डेटाबेस होल्डर क्लास बनानी होगी. इस क्लास में एक ऐसा तरीका है जो डेटाबेस मौजूद न होने पर, डेटाबेस का इंस्टेंस बनाता है या मौजूदा डेटाबेस का रेफ़रंस दिखाता है.

Room डेटाबेस पाना थोड़ा मुश्किल है. इसलिए, कोड का इस्तेमाल शुरू करने से पहले, यहां सामान्य प्रोसेस दी गई है:

  • public abstract क्लास बनाओ जो extends RoomDatabase. इस क्लास का इस्तेमाल डेटाबेस होल्डर के तौर पर किया जाता है. क्लास ऐब्स्ट्रैक्ट है, क्योंकि Room आपके लिए लागू करने की सुविधा बनाता है.
  • क्लास को @Database के साथ एनोटेट करें. आर्ग्युमेंट में, डेटाबेस के लिए इकाइयां तय करें और वर्शन नंबर सेट करें.
  • companion ऑब्जेक्ट में, ऐसा ऐब्सट्रैक्ट मैथड या प्रॉपर्टी तय करें जो SleepDatabaseDao ऑब्जेक्ट को रिटर्न करती हो. Room आपके लिए ईमेल का मुख्य हिस्सा जनरेट करेगा.
  • पूरे ऐप्लिकेशन के लिए, आपको Room डेटाबेस के सिर्फ़ एक इंस्टेंस की ज़रूरत होती है. इसलिए, RoomDatabase को सिंगलटोन बनाएं.
  • अगर डेटाबेस मौजूद नहीं है, तो डेटाबेस बनाने के लिए Room के डेटाबेस बिल्डर का इस्तेमाल करें. अगर ऐसा नहीं है, तो मौजूदा डेटाबेस दिखाएं.

पहला चरण: डेटाबेस बनाना

  1. database पैकेज में, SleepDatabase.kt खोलें.
  2. फ़ाइल में, abstract नाम की एक क्लास बनाएं. यह क्लास RoomDatabase को बढ़ाती है.

    क्लास को @Database के साथ एनोटेट करें.SleepDatabase
@Database()
abstract class SleepDatabase : RoomDatabase() {}
  1. आपको मौजूद नहीं हैं इकाइयों और वर्शन के पैरामीटर के लिए गड़बड़ी दिखेगी. @Database एनोटेशन के लिए कई आर्ग्युमेंट की ज़रूरत होती है, ताकि Room डेटाबेस बना सके.
  • SleepNight की सूची के साथ, सिर्फ़ SleepNight एट्रिब्यूट की वैल्यू सबमिट करें.entities
  • version को 1के तौर पर सेट करें. स्कीमा में बदलाव करने पर, आपको वर्शन नंबर बढ़ाना होगा.
  • स्कीमा के वर्शन के इतिहास के बैकअप सेव न करने के लिए, exportSchema को false पर सेट करें.
entities = [SleepNight::class], version = 1, exportSchema = false
  1. डेटाबेस को डीएओ के बारे में पता होना चाहिए. क्लास के मुख्य हिस्से में, ऐसी ऐब्सट्रैक्ट वैल्यू का एलान करें जो SleepDatabaseDao को रिटर्न करती है. आपके पास एक से ज़्यादा DAO हो सकते हैं.
abstract val sleepDatabaseDao: SleepDatabaseDao
  1. इसके बाद, companion ऑब्जेक्ट तय करें. साथ में मौजूद ऑब्जेक्ट की मदद से क्लाइंट, क्लास को इंस्टैंशिएट किए बिना डेटाबेस बनाने या पाने के तरीकों को ऐक्सेस कर सकते हैं. इस क्लास का मकसद सिर्फ़ डेटाबेस उपलब्ध कराना है. इसलिए, इसे कभी भी इंस्टैंटिएट करने की कोई वजह नहीं है.
 companion object {}
  1. companion ऑब्जेक्ट में, डेटाबेस के लिए एक निजी, नल वैल्यू स्वीकार करने वाला वैरिएबल INSTANCE तय करें और उसे null पर सेट करें. डेटाबेस बन जाने के बाद, INSTANCE वैरिएबल डेटाबेस का रेफ़रंस सेव करके रखेगा. इससे आपको डेटाबेस से बार-बार कनेक्शन खोलने की ज़रूरत नहीं पड़ती. ऐसा करने पर ज़्यादा शुल्क लगता है.

@Volatile की मदद से INSTANCE को एनोटेट करें. अस्थिर वैरिएबल की वैल्यू कभी कैश मेमोरी में सेव नहीं की जाएगी. साथ ही, लिखने (राइट) और पढ़ने (रीड) से जुड़े सभी काम मुख्य मेमोरी में किए जाएंगे. इससे यह पक्का करने में मदद मिलती है कि INSTANCE की वैल्यू हमेशा अप-टू-डेट हो और सभी एक्ज़ीक्यूशन थ्रेड के लिए एक जैसी हो. इसका मतलब है कि एक थ्रेड से INSTANCE में किए गए बदलाव, अन्य सभी थ्रेड को तुरंत दिखते हैं. साथ ही, आपको ऐसी स्थिति नहीं मिलती है जिसमें, मान लें कि दो थ्रेड, कैश मेमोरी में एक ही इकाई को अपडेट कर रही हैं. इससे समस्या हो सकती है.

@Volatile
private var INSTANCE: SleepDatabase? = null
  1. नीचे दिए गए INSTANCE में, अब भी companion ऑब्जेक्ट के अंदर, Context पैरामीटर के साथ getInstance()तरीका तय करें. इसकी ज़रूरत डेटाबेस बिल्डर को होगी. SleepDatabase टाइप का डेटा दिखाता है. आपको एक गड़बड़ी दिखेगी, क्योंकि getInstance() अभी तक कुछ भी रिटर्न नहीं कर रहा है.
fun getInstance(context: Context): SleepDatabase {}
  1. getInstance() के अंदर, synchronized{} ब्लॉक जोड़ें. this पास करें, ताकि आपके पास कॉन्टेक्स्ट का ऐक्सेस हो.

    ऐसा हो सकता है कि कई थ्रेड किसी डेटाबेस इंस्टेंस से एक ही समय पर अनुरोध करें. इसकी वजह से, एक के बजाय दो डेटाबेस बन सकते हैं. इस सैंपल ऐप्लिकेशन में यह समस्या नहीं होती है. हालांकि, ज़्यादा जटिल ऐप्लिकेशन में ऐसा हो सकता है. डेटाबेस को synchronized में लाने के लिए, कोड को रैप करें. इसका मतलब है कि एक समय पर एक ही कोड एक्ज़ीक्यूट करने पर, कोड का यह ब्लॉक डाल सकता है. इससे यह पक्का होता है कि डेटाबेस को सिंक करने की शुरुआत एक ही बार की गई है.
synchronized(this) {}
  1. सिंक किए गए ब्लॉक में, INSTANCE की मौजूदा वैल्यू को लोकल वैरिएबल instance में कॉपी करें. ऐसा स्मार्ट कास्ट का फ़ायदा पाने के लिए किया जाता है. यह सुविधा सिर्फ़ लोकल वैरिएबल के लिए उपलब्ध है.
var instance = INSTANCE
  1. synchronized ब्लॉक के अंदर, synchronized ब्लॉक के आखिर में return instance. रिटर्न टाइप के मेल न खाने की गड़बड़ी को अनदेखा करें. जब आपका काम पूरा हो जाएगा, तब आपको कभी भी शून्य नहीं मिलेगा.
return instance
  1. return स्टेटमेंट के ऊपर, if स्टेटमेंट जोड़ें. इससे यह पता चलेगा कि instance शून्य है या नहीं. इसका मतलब है कि अब तक कोई डेटाबेस नहीं है.
if (instance == null) {}
  1. अगर instance null है, तो डेटाबेस पाने के लिए डेटाबेस बिल्डर का इस्तेमाल करें. if स्टेटमेंट के मुख्य हिस्से में, Room.databaseBuilder को लागू करें. साथ ही, वह कॉन्टेक्स्ट, डेटाबेस क्लास, और डेटाबेस का नाम sleep_history_database दें जिसे आपने पास किया है. इस गड़बड़ी को हटाने के लिए, आपको माइग्रेशन की रणनीति और build() को इन चरणों में जोड़ना होगा.
instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database")
  1. बिल्डर में, माइग्रेशन की ज़रूरी रणनीति जोड़ें. .fallbackToDestructiveMigration()

    का इस्तेमाल करें.आम तौर पर, स्कीमा में बदलाव होने पर आपको माइग्रेशन ऑब्जेक्ट के साथ माइग्रेशन की रणनीति देनी होती है. माइग्रेशन ऑब्जेक्ट एक ऐसा ऑब्जेक्ट होता है जो यह तय करता है कि पुराने स्कीमा वाली सभी लाइनों को नए स्कीमा वाली लाइनों में कैसे बदला जाए, ताकि कोई डेटा न मिटे. माइग्रेशन, इस कोडलैब के दायरे से बाहर है. इसका आसान तरीका यह है कि डेटाबेस को डिस्ट्रॉय करके फिर से बनाया जाए. इसका मतलब है कि डेटा मिट जाएगा.
.fallbackToDestructiveMigration()
  1. आखिर में, कॉल करें .build().
.build()
  1. if स्टेटमेंट में, INSTANCE = instance को आखिरी चरण के तौर पर असाइन करें.
INSTANCE = instance
  1. आपका फ़ाइनल कोड ऐसा दिखना चाहिए:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {

   abstract val sleepDatabaseDao: SleepDatabaseDao

   companion object {

       @Volatile
       private var INSTANCE: SleepDatabase? = null

       fun getInstance(context: Context): SleepDatabase {
           synchronized(this) {
               var instance = INSTANCE

               if (instance == null) {
                   instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database"
                   )
                           .fallbackToDestructiveMigration()
                           .build()
                   INSTANCE = instance
               }
               return instance
           }
       }
   }
}
  1. अपना कोड बनाएं और उसे चलाएं.

अब आपके पास Room डेटाबेस के साथ काम करने के लिए सभी बिल्डिंग ब्लॉक हैं. यह कोड कंपाइल और रन होता है. हालांकि, आपके पास यह पता लगाने का कोई तरीका नहीं है कि यह कोड सही तरीके से काम कर रहा है या नहीं. इसलिए, यह कुछ बुनियादी टेस्ट जोड़ने का सही समय है.

दूसरा चरण: SleepDatabase की जांच करना

इस चरण में, आपको दी गई जांचों को पूरा करना होता है. इससे यह पुष्टि की जाती है कि आपका डेटाबेस काम कर रहा है. इससे यह पक्का करने में मदद मिलती है कि डेटाबेस काम कर रहा है या नहीं. ये टेस्ट बुनियादी हैं. प्रोडक्शन ऐप्लिकेशन के लिए, आपको सभी डीएओ में सभी फ़ंक्शन और क्वेरी का इस्तेमाल करना होगा.

स्टार्टर ऐप्लिकेशन में androidTest फ़ोल्डर होता है. इस androidTest फ़ोल्डर में यूनिट टेस्ट शामिल होते हैं. इनमें Android इंस्ट्रुमेंटेशन शामिल होता है. इसका मतलब है कि टेस्ट के लिए Android फ़्रेमवर्क की ज़रूरत होती है. इसलिए, आपको टेस्ट को किसी फ़िज़िकल या वर्चुअल डिवाइस पर चलाना होगा. ज़ाहिर है, Android फ़्रेमवर्क के बिना भी यूनिट टेस्ट बनाई और चलाई जा सकती हैं.

  1. Android Studio में, androidTest फ़ोल्डर में जाकर, SleepDatabaseTest फ़ाइल खोलें.
  2. कोड से टिप्पणी हटाने के लिए, टिप्पणी किए गए सभी कोड को चुनें और Cmd+/ या Control+/ कीबोर्ड शॉर्टकट दबाएं.
  3. फ़ाइल देखें.

यहां टेस्टिंग कोड के बारे में खास जानकारी दी गई है, क्योंकि यह एक ऐसा कोड है जिसे दोबारा इस्तेमाल किया जा सकता है:

  • SleepDabaseTest एक टेस्ट क्लास है.
  • @RunWith एनोटेशन, टेस्ट रनर की पहचान करता है. यह वह प्रोग्राम होता है जो टेस्ट सेट अप करता है और उन्हें लागू करता है.
  • सेटअप के दौरान, @Before के साथ एनोटेट किए गए फ़ंक्शन को लागू किया जाता है. इससे मेमोरी में मौजूद SleepDatabase, SleepDatabaseDao के साथ बनता है. "इन-मेमोरी" का मतलब है कि यह डेटाबेस, फ़ाइल सिस्टम में सेव नहीं किया जाता. साथ ही, टेस्ट पूरे होने के बाद इसे मिटा दिया जाता है.
  • साथ ही, इन-मेमोरी डेटाबेस बनाते समय, कोड टेस्ट के लिए खास तौर पर बनाए गए दूसरे तरीके, allowMainThreadQueries को कॉल करता है. डिफ़ॉल्ट रूप से, मुख्य थ्रेड पर क्वेरी चलाने की कोशिश करने पर आपको गड़बड़ी का मैसेज मिलता है. इस तरीके से, मुख्य थ्रेड पर टेस्ट चलाए जा सकते हैं. हालांकि, ऐसा सिर्फ़ टेस्टिंग के दौरान ही करना चाहिए.
  • @Test एनोटेशन वाली टेस्ट विधि में, SleepNight बनाया, डाला, और वापस पाया जाता है. साथ ही, यह दावा किया जाता है कि वे एक ही हैं. अगर कोई गड़बड़ी होती है, तो अपवाद दिखाएं. असल टेस्ट में, आपके पास कई @Test तरीके होते हैं.
  • जांच पूरी होने के बाद, @After के साथ एनोटेट किया गया फ़ंक्शन, डेटाबेस को बंद करने के लिए एक्ज़ीक्यूट होता है.
  1. प्रोजेक्ट पैन में मौजूद टेस्ट फ़ाइल पर राइट क्लिक करें और 'SleepDatabaseTest' चलाएं को चुनें.
  2. जांच पूरी होने के बाद, SleepDatabaseTest पैनल में जाकर पुष्टि करें कि सभी जांच पास हो गई हैं.

सभी टेस्ट पास हो गए हैं. इसलिए, अब आपको कई चीज़ों के बारे में पता चल गया है:

  • डेटाबेस सही तरीके से बन जाता है.
  • डेटाबेस में SleepNight डाला जा सकता है.
  • आपको SleepNight वापस मिल सकता है.
  • SleepNight एट्रिब्यूट की वैल्यू, क्वालिटी के हिसाब से सही है.

Android Studio प्रोजेक्ट: TrackMySleepQualityRoomAndTesting

किसी डेटाबेस की टेस्टिंग करते समय, आपको डीएओ में तय किए गए सभी तरीकों का इस्तेमाल करना होगा. जांच पूरी करने के लिए, अन्य DAO तरीकों को आज़माने के लिए, जांच जोड़ें और उन्हें लागू करें.

  • अपनी टेबल को @Entity एनोटेशन वाली डेटा क्लास के तौर पर तय करें. टेबल में, @ColumnInfo एनोटेशन वाली प्रॉपर्टी को कॉलम के तौर पर तय करें.
  • डेटा ऐक्सेस ऑब्जेक्ट (डीएओ) को @Dao के साथ एनोटेट किए गए इंटरफ़ेस के तौर पर तय करें. डीएओ, Kotlin फ़ंक्शन को डेटाबेस क्वेरी से मैप करता है.
  • @Insert, @Delete, और @Update फ़ंक्शन तय करने के लिए, एनोटेशन का इस्तेमाल करें.
  • किसी भी अन्य क्वेरी के लिए, SQLite क्वेरी स्ट्रिंग के साथ @Query एनोटेशन का इस्तेमाल करें.
  • एक ऐब्स्ट्रैक्ट क्लास बनाएं, जिसमें getInstance() फ़ंक्शन हो. यह फ़ंक्शन, डेटाबेस दिखाता है.
  • इंस्ट्रुमेंटेड टेस्ट का इस्तेमाल करके, यह जांच करें कि आपका डेटाबेस और डीएओ उम्मीद के मुताबिक काम कर रहे हैं या नहीं. दी गई जांचों को टेंप्लेट के तौर पर इस्तेमाल किया जा सकता है.

Udacity का कोर्स:

Android डेवलपर का दस्तावेज़:

अन्य दस्तावेज़ और लेख:

इस सेक्शन में, उन छात्र-छात्राओं के लिए होमवर्क असाइनमेंट की सूची दी गई है जो किसी शिक्षक के कोर्स के हिस्से के तौर पर इस कोडलैब पर काम कर रहे हैं. शिक्षक के पास ये विकल्प होते हैं:

  • अगर ज़रूरी हो, तो होमवर्क असाइन करें.
  • छात्र-छात्राओं को बताएं कि होमवर्क असाइनमेंट कैसे सबमिट किए जाते हैं.
  • होमवर्क असाइनमेंट को ग्रेड दें.

शिक्षक इन सुझावों का इस्तेमाल अपनी ज़रूरत के हिसाब से कर सकते हैं. साथ ही, वे चाहें, तो कोई दूसरा होमवर्क भी दे सकते हैं.

अगर आपको यह कोडलैब खुद से पूरा करना है, तो अपनी जानकारी की जांच करने के लिए, इन होमवर्क असाइनमेंट का इस्तेमाल करें.

इन सवालों के जवाब दें

पहला सवाल

यह कैसे पता चलता है कि कोई क्लास, Room डेटाबेस में सेव की जाने वाली इकाई को दिखाती है?

  • क्लास को एक्सटेंड करें DatabaseEntity.
  • क्लास को @Entity के साथ एनोटेट करें.
  • क्लास को @Database के साथ एनोटेट करें.
  • क्लास को RoomEntity के तौर पर एक्सटेंड करें और क्लास को @Room के साथ एनोटेट करें.

दूसरा सवाल

डीएओ (डेटा ऐक्सेस ऑब्जेक्ट) एक ऐसा इंटरफ़ेस है जिसका इस्तेमाल Room, Kotlin फ़ंक्शन को डेटाबेस क्वेरी में मैप करने के लिए करता है.

यह कैसे पता चलेगा कि कोई इंटरफ़ेस, Room डेटाबेस के लिए डीएओ को दिखाता है?

  • इंटरफ़ेस को बड़ा करें RoomDAO.
  • इंटरफ़ेस को EntityDao तक बढ़ाएं. इसके बाद, DaoConnection() तरीके को लागू करें.
  • @Dao की मदद से इंटरफ़ेस में एनोटेशन जोड़ें.
  • @RoomConnection की मदद से इंटरफ़ेस में एनोटेशन जोड़ें.

तीसरा सवाल

Room डेटाबेस के बारे में इनमें से कौनसी बातें सही हैं? लागू होने वाले सभी विकल्प चुनें.

  • एनोटेट की गई डेटा क्लास के तौर पर, Room डेटाबेस के लिए टेबल तय की जा सकती हैं.
  • अगर आपने किसी क्वेरी से LiveData को वापस लाया है, तो Room, LiveData में बदलाव होने पर उसे अपडेट करता रहेगा.LiveData
  • हर Room डेटाबेस में एक और सिर्फ़ एक DAO होना चाहिए.
  • किसी क्लास को Room डेटाबेस के तौर पर पहचानने के लिए, उसे RoomDatabase की सबक्लास बनाएं और उसे @Database से एनोटेट करें.

चौथा सवाल

@Dao इंटरफ़ेस में, इनमें से कौनसे एनोटेशन इस्तेमाल किए जा सकते हैं? लागू होने वाले सभी विकल्प चुनें.

  • @Get
  • @Update
  • @Insert
  • @Query

पांचवां सवाल

यह कैसे पुष्टि की जा सकती है कि आपका डेटाबेस काम कर रहा है? लागू होने वाले सभी विकल्पों को चुनें.

  • इंस्ट्रूमेंट किए गए टेस्ट लिखें.
  • जब तक ऐप्लिकेशन डेटा नहीं दिखाता, तब तक उसे लिखना और चलाना जारी रखें.
  • डीएओ इंटरफ़ेस में मौजूद तरीकों के कॉल को Entity क्लास में मौजूद मिलते-जुलते तरीकों के कॉल से बदलें.
  • Room लाइब्रेरी की ओर से उपलब्ध कराए गए verifyDatabase() फ़ंक्शन को चलाएं.

अगला सबक शुरू करें: 6.2 कोरूटीन और रूम

इस कोर्स में मौजूद अन्य कोडलैब के लिंक के लिए, Android Kotlin Fundamentals कोडलैब का लैंडिंग पेज देखें.