(ज़रूरी नहीं) Firebase लोकल एम्युलेटर सुइट की मदद से प्रोटोटाइप बनाएं और टेस्ट करें
आपका ऐप्लिकेशन रीयलटाइम डेटाबेस से कैसे डेटा लेता है और उसमें क्या लिखा जाता है, इस बारे में बात करने से पहले, आइए ऐसे टूल के बारे में बताते हैं जिनका इस्तेमाल करके, रीयलटाइम डेटाबेस के काम करने के प्रोटोटाइप और की जांच की जा सकती है: Firebase लोकल एम्युलेटर सुइट. अगर अलग-अलग डेटा मॉडल आज़माए जा रहे हैं, सुरक्षा के नियमों को ऑप्टिमाइज़ किया जा रहा है या बैक-एंड से इंटरैक्ट करने का सबसे किफ़ायती तरीका खोजा जा रहा है, तो लाइव सेवाओं को डिप्लॉय किए बिना, स्थानीय तौर पर काम करना अच्छा रहेगा.
रीयल टाइम डेटाबेस एम्युलेटर, Local Emulator Suite का हिस्सा होता है. इससे आपका ऐप्लिकेशन, एम्युलेट किए गए डेटाबेस के कॉन्टेंट और कॉन्फ़िगरेशन से इंटरैक्ट कर पाता है. साथ ही, वह एम्युलेट किए गए प्रोजेक्ट के संसाधनों (फ़ंक्शन, दूसरे डेटाबेस, और सुरक्षा के नियम) से भी इंटरैक्ट करता है.
रीयलटाइम डेटाबेस एम्युलेटर का इस्तेमाल करने के लिए, आपको कुछ ही चरण पूरे करने होंगे:
- एम्युलेटर से कनेक्ट करने के लिए, अपने ऐप्लिकेशन के टेस्ट कॉन्फ़िगरेशन में कोड की एक लाइन जोड़ना.
- आपकी लोकल प्रोजेक्ट डायरेक्ट्री के रूट से,
firebase emulators:start
पर चल रहा है. - हमेशा की तरह, रीयलटाइम डेटाबेस प्लैटफ़ॉर्म एसडीके का इस्तेमाल करके या रीयलटाइम डेटाबेस REST API का इस्तेमाल करके, अपने ऐप्लिकेशन के प्रोटोटाइप कोड से कॉल करना.
रीयल टाइम डेटाबेस और Cloud Functions के बारे में ज़्यादा जानकारी उपलब्ध है. आपको लोकल एम्युलेटर सुइट के बारे में जानकारी भी देखनी चाहिए.
FIRDatabaseReference पाएं
डेटाबेस से डेटा पढ़ने या उसमें बदलाव करने के लिए, आपके पास FIRDatabaseReference
का एक इंस्टेंस होना चाहिए:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
डेटा सेव करने की अनुमति दें
इस दस्तावेज़ में Firebase डेटा को पढ़ने और लिखने से जुड़ी बुनियादी जानकारी दी गई है.
Firebase डेटा को Database
रेफ़रंस के तौर पर लिखा जाता है और रेफ़रंस के साथ एसिंक्रोनस लिसनर जोड़कर, इसे वापस लाया जाता है. लिसनर को डेटा की शुरुआती स्थिति के लिए एक बार ट्रिगर किया जाता है. इसके बाद, डेटा में कभी भी बदलाव होता है.
लिखने से जुड़ी बुनियादी कार्रवाइयां
लिखने से जुड़ी बुनियादी कार्रवाइयों के लिए, setValue
का इस्तेमाल करके किसी खास रेफ़रंस में डेटा सेव किया जा सकता है. इसके लिए, पाथ के मौजूदा डेटा को बदला जा सकता है. इस तरीके का इस्तेमाल करके:
- उपलब्ध JSON टाइप के मुताबिक पास के टाइप:
NSString
NSNumber
NSDictionary
NSArray
उदाहरण के लिए, setValue
वाले किसी उपयोगकर्ता को इस तरह जोड़ा जा सकता है:
Swift
self.ref.child("users").child(user.uid).setValue(["username": username])
Objective-C
[[[self.ref child:@"users"] child:authResult.user.uid] setValue:@{@"username": username}];
इस तरह setValue
का इस्तेमाल करने से, बताई गई जगह का डेटा ओवरराइट हो जाता है. इसमें, कोई भी चाइल्ड नोड शामिल है. हालांकि, पूरे ऑब्जेक्ट को फिर से लिखे बिना भी बच्चे को अपडेट किया जा सकता है. अगर आप उपयोगकर्ताओं को उनकी प्रोफ़ाइल अपडेट करने की अनुमति देना चाहते हैं
तो उपयोगकर्ता नाम को इस तरह से अपडेट करें:
Swift
self.ref.child("users/\(user.uid)/username").setValue(username)
Objective-C
[[[[_ref child:@"users"] child:user.uid] child:@"username"] setValue:username];
डेटा पढ़ें
वैल्यू इवेंट को सुनकर डेटा देखना
पाथ का डेटा पढ़ने और बदलावों को सुनने के लिए, FIRDatabaseReference
के observeEventType:withBlock
का इस्तेमाल करके FIRDataEventTypeValue
इवेंट देखें.
इवेंट प्रकार | आम तौर पर इस्तेमाल |
---|---|
FIRDataEventTypeValue |
पाथ की पूरी सामग्री में हुए बदलावों को पढ़ और सुन सकता है. |
किसी दिए गए पाथ से मिले डेटा को पढ़ने के लिए, FIRDataEventTypeValue
इवेंट का इस्तेमाल किया जा सकता है.
ऐसा इसलिए, क्योंकि यह इवेंट के समय मौजूद होता है. यह तरीका, ऑडियंस के अटैच होने पर एक बार ट्रिगर होता है. इसके बाद, जब भी डेटा में बदलाव होता है, तो इसमें चाइल्ड भी शामिल
होता है. इवेंट कॉलबैक को एक snapshot
पास किया जाता है, जिसमें उस जगह का पूरा डेटा होता है. इसमें चाइल्ड डेटा भी शामिल होता है. अगर कोई डेटा मौजूद नहीं है, तो exists()
और nil
को कॉल करने पर स्नैपशॉट में false
दिखेगा. ऐसा तब होगा, जब exists()
और nil
की value
प्रॉपर्टी को पढ़ा जाएगा.
नीचे दिए गए उदाहरण में सोशल ब्लॉगिंग ऐप्लिकेशन के बारे में बताया गया है, जो डेटाबेस से पोस्ट की जानकारी हासिल करता है:
Swift
refHandle = postRef.observe(DataEventType.value, with: { snapshot in // ... })
Objective-C
_refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { NSDictionary *postDict = snapshot.value; // ... }];
सुनने वाले को एक FIRDataSnapshot
मिलता है, जिसमें value
प्रॉपर्टी में इवेंट के समय डेटाबेस में तय जगह का डेटा शामिल होता है. आपके पास, सही नेटिव टाइप के लिए वैल्यू असाइन करने का विकल्प है, जैसे कि NSDictionary
.
अगर जगह के लिए कोई डेटा मौजूद नहीं है, तो value
nil
है.
डेटा को एक बार पढ़ें
getData() का इस्तेमाल करके एक बार पढ़ें
SDK टूल को डेटाबेस सर्वर के साथ इंटरैक्शन को मैनेज करने के लिए डिज़ाइन किया गया है. इससे कोई फ़र्क़ नहीं पड़ता कि आपका ऐप्लिकेशन ऑनलाइन है या ऑफ़लाइन.
आम तौर पर, बैकएंड से डेटा के अपडेट की सूचना पाने के लिए, आपको ऊपर बताई गई वैल्यू इवेंट तकनीकों का इस्तेमाल करना चाहिए. ये तकनीक आपके इस्तेमाल और बिलिंग को कम करती हैं. साथ ही, इन्हें आपके उपयोगकर्ताओं को ऑनलाइन और ऑफ़लाइन होने पर सबसे अच्छा अनुभव देने के लिए ऑप्टिमाइज़ किया जाता है.
अगर आपको सिर्फ़ एक बार डेटा की ज़रूरत है, तो getData()
का इस्तेमाल करके डेटाबेस के डेटा का स्नैपशॉट पाएं. अगर किसी वजह से getData()
, सर्वर वैल्यू को नहीं दिखा पाता है, तो क्लाइंट लोकल स्टोरेज कैश की जांच करेगा और अगर वैल्यू अब भी नहीं मिलती है, तो वह गड़बड़ी दिखाएगा.
नीचे दिए गए उदाहरण में, उपयोगकर्ता के सार्वजनिक तौर पर इस्तेमाल होने वाले उपयोगकर्ता नाम को डेटाबेस से एक बार में वापस पाने के बारे में बताया गया है:
Swift
do { let snapshot = try await ref.child("users/\(uid)/username").getData() let userName = snapshot.value as? String ?? "Unknown" } catch { print(error) }
Objective-C
NSString *userPath = [NSString stringWithFormat:@"users/%@/username", uid]; [[ref child:userPath] getDataWithCompletionBlock:^(NSError * _Nullable error, FIRDataSnapshot * _Nonnull snapshot) { if (error) { NSLog(@"Received an error %@", error); return; } NSString *userName = snapshot.value; }];
getData()
का ग़ैर-ज़रूरी इस्तेमाल करने से बैंडविथ का इस्तेमाल बढ़ सकता है और परफ़ॉर्मेंस में कमी आ सकती है. जैसा कि ऊपर दिखाया गया है, रीयलटाइम लिसनर का इस्तेमाल करके इस समस्या को रोका जा सकता है.
ऑब्ज़र्वर की मदद से एक बार डेटा पढ़ें
कुछ मामलों में, हो सकता है कि आप सर्वर पर अपडेट की गई वैल्यू की जांच करने के बजाय, लोकल कैश मेमोरी से वैल्यू तुरंत लौटाना चाहें. ऐसे मामलों में, observeSingleEventOfType
का इस्तेमाल करके, डिवाइस की डिस्क कैश मेमोरी से डेटा तुरंत हासिल किया जा सकता है.
यह ऐसे डेटा के लिए काम का है जिसे सिर्फ़ एक बार लोड करने की ज़रूरत होती है. साथ ही, जिसके बार-बार बदलने या सुनने की ज़रूरत नहीं होती. उदाहरण के लिए, पिछले उदाहरणों में दिए गए ब्लॉगिंग ऐप्लिकेशन में, उपयोगकर्ता की प्रोफ़ाइल को लोड करने के लिए इस तरीके का इस्तेमाल किया जाता है. ऐसा तब होता है, जब उपयोगकर्ता नई पोस्ट लिखना शुरू करते हैं:
Swift
let userID = Auth.auth().currentUser?.uid ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { snapshot in // Get user value let value = snapshot.value as? NSDictionary let username = value?["username"] as? String ?? "" let user = User(username: username) // ... }) { error in print(error.localizedDescription) }
Objective-C
NSString *userID = [FIRAuth auth].currentUser.uid; [[[_ref child:@"users"] child:userID] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { // Get user value User *user = [[User alloc] initWithUsername:snapshot.value[@"username"]]; // ... } withCancelBlock:^(NSError * _Nonnull error) { NSLog(@"%@", error.localizedDescription); }];
डेटा अपडेट करना या मिटाना
खास फ़ील्ड अपडेट करें
दूसरे चाइल्ड नोड को ओवरराइट किए बिना, किसी नोड के खास चिल्ड्रेन को एक साथ लिखने के लिए, updateChildValues
तरीके का इस्तेमाल करें.
updateChildValues
को कॉल करते समय, बटन के लिए पाथ बताकर, लोअर-लेवल चाइल्ड वैल्यू अपडेट की जा सकती हैं. अगर बेहतर तरीके से स्केल करने के लिए डेटा को कई जगहों पर सेव किया जाता है, तो उस डेटा के सभी इंस्टेंस अपडेट किए जा सकते हैं. इसके लिए, डेटा फ़ैन-आउट का इस्तेमाल करें. उदाहरण के लिए, हो सकता है कि कोई सोशल ब्लॉगिंग ऐप्लिकेशन, पोस्ट बनाने के साथ-साथ उसे हाल की गतिविधि फ़ीड और पोस्ट करने वाले उपयोगकर्ता की गतिविधि फ़ीड में अपडेट करना चाहे. ऐसा करने के लिए, ब्लॉगिंग ऐप्लिकेशन इस तरह के कोड का इस्तेमाल करता है:
Swift
guard let key = ref.child("posts").childByAutoId().key else { return } let post = ["uid": userID, "author": username, "title": title, "body": body] let childUpdates = ["/posts/\(key)": post, "/user-posts/\(userID)/\(key)/": post] ref.updateChildValues(childUpdates)
Objective-C
NSString *key = [[_ref child:@"posts"] childByAutoId].key; NSDictionary *post = @{@"uid": userID, @"author": username, @"title": title, @"body": body}; NSDictionary *childUpdates = @{[@"/posts/" stringByAppendingString:key]: post, [NSString stringWithFormat:@"/user-posts/%@/%@/", userID, key]: post}; [_ref updateChildValues:childUpdates];
इस उदाहरण में /posts/$postid
के सभी उपयोगकर्ताओं के लिए पोस्ट वाले नोड में एक पोस्ट बनाने और getKey()
की मदद से कुंजी पाने के लिए, childByAutoId
का इस्तेमाल किया गया है. इसके बाद, /user-posts/$userid/$postid
पर उपयोगकर्ता की पोस्ट में दूसरी एंट्री बनाने के लिए, कुंजी का इस्तेमाल किया जा सकता है.
इन पाथ का इस्तेमाल करके, updateChildValues
को एक ही कॉल करके JSON ट्री में कई जगहों को एक साथ अपडेट किया जा सकता है. जैसे, यह उदाहरण दोनों जगहों पर नई पोस्ट बनाने का तरीका क्या है. इस तरह से एक साथ किए जाने वाले अपडेट छोटे होते हैं: या तो सभी अपडेट सफल होते हैं या सभी अपडेट नहीं हो पाते हैं.
पूरा करने वाला ब्लॉक जोड़ें
अगर आप जानना चाहते हैं कि आपका डेटा कब सेव किया गया है, तो आप
पूरा होने वाला ब्लॉक जोड़ सकते हैं. setValue
और updateChildValues
दोनों, पूरा होने का एक वैकल्पिक ब्लॉक लेते हैं. इसे तब कॉल किया जाता है, जब डेटाबेस पर डेटा लिखना तय किया जाता है. इस लिसनर की मदद से, यह ट्रैक किया जा सकता है कि कौनसा डेटा सेव किया गया है और कौनसा डेटा अब भी सिंक किया जा रहा है. अगर कॉल पूरा नहीं हो सका, तो
लिसनर को गड़बड़ी वाला एक ऑब्जेक्ट भेजा जाता है. इसमें गड़बड़ी की वजह बताई जाती है.
Swift
do { try await ref.child("users").child(user.uid).setValue(["username": username]) print("Data saved successfully!") } catch { print("Data could not be saved: \(error).") }
Objective-C
[[[_ref child:@"users"] child:user.uid] setValue:@{@"username": username} withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) { if (error) { NSLog(@"Data could not be saved: %@", error); } else { NSLog(@"Data saved successfully."); } }];
डेटा मिटाना
डेटा मिटाने का सबसे आसान तरीका यह है कि उस डेटा की जगह के रेफ़रंस पर removeValue
को कॉल किया जाए.
वैल्यू के तौर पर nil
को तय करके भी मिटाया जा सकता है.
जैसे, setValue
या updateChildValues
. इस तकनीक का इस्तेमाल updateChildValues
के साथ करके, एक एपीआई कॉल में एक से ज़्यादा चिल्ड्रेन की जानकारी मिटाने के लिए किया जा सकता है.
लिसनर को अलग करें
ViewController
को छोड़ने पर, ऑब्ज़र्वर अपने-आप डेटा सिंक करना बंद नहीं करते. अगर ऑब्ज़र्वर को ठीक से नहीं हटाया गया, तो यह डेटा को लोकल मेमोरी में सिंक
करता रहेगा. जब किसी ऑब्ज़र्वर की ज़रूरत न हो, तो उससे जुड़े FIRDatabaseHandle
को removeObserverWithHandle
तरीके से पास करके उसे हटाएं.
किसी पहचान फ़ाइल में कॉलबैक ब्लॉक जोड़ने पर, FIRDatabaseHandle
दिखता है.
इन हैंडल का इस्तेमाल कॉलबैक ब्लॉक को हटाने के लिए किया जा सकता है.
अगर किसी डेटाबेस रेफ़रंस में एक से ज़्यादा लिसनर जोड़े गए हैं, तो किसी इवेंट के शुरू होने पर हर लिसनर को कॉल किया जाता है. उस जगह पर डेटा को सिंक होने से रोकने के लिए, आपको उस जगह पर मौजूद सभी ऑब्ज़र्वर को हटाना होगा. इसके लिए, आपको removeAllObservers
तरीके का इस्तेमाल करना होगा.
लिसनर पर removeObserverWithHandle
या removeAllObservers
को कॉल करने से, इसके चाइल्ड नोड पर रजिस्टर किए गए लिसनर अपने-आप नहीं हटते. उन्हें हटाने के लिए आपको उन रेफ़रंस या हैंडल को भी ट्रैक करना होगा.
डेटा को लेन-देन के तौर पर सेव करें
इंंक्रीमेंटल काउंटर जैसे बदलावों की वजह से खराब हो सकने वाले डेटा के साथ काम करते समय, ट्रांज़ैक्शन ऑपरेशन इस्तेमाल किया जा सकता है. आप इस कार्रवाई को दो तर्क देते हैं: एक अपडेट फ़ंक्शन और एक वैकल्पिक पूर्णता कॉलबैक. अपडेट फ़ंक्शन, डेटा की मौजूदा स्थिति को आर्ग्युमेंट के तौर पर लेता है और वह नई वैल्यू दिखाता है जिसे आपको लिखना है.
उदाहरण के लिए, उदाहरण के तौर पर दिए गए सोशल ब्लॉगिंग ऐप्लिकेशन में, उपयोगकर्ताओं को पोस्ट पर स्टार का निशान लगाने या हटाने का विकल्प दिया जा सकता है. साथ ही, यह भी ट्रैक किया जा सकता है कि किसी पोस्ट को कितने स्टार मिले हैं.
Swift
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in if var post = currentData.value as? [String: AnyObject], let uid = Auth.auth().currentUser?.uid { var stars: [String: Bool] stars = post["stars"] as? [String: Bool] ?? [:] var starCount = post["starCount"] as? Int ?? 0 if let _ = stars[uid] { // Unstar the post and remove self from stars starCount -= 1 stars.removeValue(forKey: uid) } else { // Star the post and add self to stars starCount += 1 stars[uid] = true } post["starCount"] = starCount as AnyObject? post["stars"] = stars as AnyObject? // Set value and report transaction success currentData.value = post return TransactionResult.success(withValue: currentData) } return TransactionResult.success(withValue: currentData) }) { error, committed, snapshot in if let error = error { print(error.localizedDescription) } }
Objective-C
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) { NSMutableDictionary *post = currentData.value; if (!post || [post isEqual:[NSNull null]]) { return [FIRTransactionResult successWithValue:currentData]; } NSMutableDictionary *stars = post[@"stars"]; if (!stars) { stars = [[NSMutableDictionary alloc] initWithCapacity:1]; } NSString *uid = [FIRAuth auth].currentUser.uid; int starCount = [post[@"starCount"] intValue]; if (stars[uid]) { // Unstar the post and remove self from stars starCount--; [stars removeObjectForKey:uid]; } else { // Star the post and add self to stars starCount++; stars[uid] = @YES; } post[@"stars"] = stars; post[@"starCount"] = @(starCount); // Set value and report transaction success currentData.value = post; return [FIRTransactionResult successWithValue:currentData]; } andCompletionBlock:^(NSError * _Nullable error, BOOL committed, FIRDataSnapshot * _Nullable snapshot) { // Transaction completed if (error) { NSLog(@"%@", error.localizedDescription); } }];
अगर कई उपयोगकर्ता एक ही समय पर एक ही पोस्ट पर स्टार का निशान लगाते हैं या क्लाइंट के पास पुराना डेटा है, तो लेन-देन का इस्तेमाल करने से स्टार काउंट गलत नहीं होगा. FIRMutableData
क्लास में शामिल वैल्यू, शुरुआत में पाथ के लिए क्लाइंट की आखिरी वैल्यू होती है. अगर कोई वैल्यू नहीं है, तो nil
उसे माना जाता है. सर्वर, शुरुआती वैल्यू की तुलना उसकी मौजूदा वैल्यू से करता है. साथ ही, वैल्यू के मेल खाने या उसे अस्वीकार करने पर ट्रांज़ैक्शन को स्वीकार करता है. अगर ट्रांज़ैक्शन अस्वीकार हो जाता है, तो सर्वर क्लाइंट को मौजूदा वैल्यू दिखाता है, जो अपडेट की गई वैल्यू के साथ ट्रांज़ैक्शन को फिर से चलाता है. ऐसा तब तक किया जाता है, जब तक लेन-देन स्वीकार नहीं किया जाता या
कई बार कोशिश नहीं की जाती.
ऐटमिक सर्वर-साइड इंक्रीमेंट
ऊपर दिए गए इस्तेमाल के उदाहरण में, हम डेटाबेस में दो वैल्यू लिख रहे हैं: पोस्ट पर स्टार का निशान लगाने या हटाने वाले उपयोगकर्ता का आईडी और बढ़ते हुए स्टार की संख्या. अगर हमें पहले से ही पता है कि उपयोगकर्ता पोस्ट पर स्टार का निशान लगा रहा है, तो हम लेन-देन के बजाय ऐटॉमिक इंक्रीमेंट की सुविधा का इस्तेमाल कर सकते हैं.
Swift
let updates = [ "posts/\(postID)/stars/\(userID)": true, "posts/\(postID)/starCount": ServerValue.increment(1), "user-posts/\(postID)/stars/\(userID)": true, "user-posts/\(postID)/starCount": ServerValue.increment(1) ] as [String : Any] Database.database().reference().updateChildValues(updates)
Objective-C
NSDictionary *updates = @{[NSString stringWithFormat: @"posts/%@/stars/%@", postID, userID]: @TRUE, [NSString stringWithFormat: @"posts/%@/starCount", postID]: [FIRServerValue increment:@1], [NSString stringWithFormat: @"user-posts/%@/stars/%@", postID, userID]: @TRUE, [NSString stringWithFormat: @"user-posts/%@/starCount", postID]: [FIRServerValue increment:@1]}; [[[FIRDatabase database] reference] updateChildValues:updates];
यह कोड किसी लेन-देन की कार्रवाई का इस्तेमाल नहीं करता, इसलिए विरोधाभासी अपडेट होने पर यह अपने आप फिर से नहीं चलता. हालांकि, बढ़ती हुई कार्रवाई सीधे डेटाबेस सर्वर पर होती है, इसलिए किसी समस्या की संभावना नहीं होती.
यदि आप ऐप्लिकेशन-विशिष्ट विरोधाभासों का पता लगाना और अस्वीकार करना चाहते हैं, जैसे कोई उपयोगकर्ता जिस पोस्ट पर स्टार का निशान लगा रहा है जिसे वे पहले ही तारांकित कर चुके हैं, तो आपको उस उपयोग के उदाहरण के लिए कस्टम सुरक्षा नियम लिखना चाहिए.
डेटा के साथ ऑफ़लाइन काम करना
अगर किसी क्लाइंट का इंटरनेट कनेक्शन बंद हो जाता है, तो आपका ऐप्लिकेशन सही तरीके से काम करता रहेगा.
Firebase डेटाबेस से कनेक्ट हर क्लाइंट, किसी भी चालू डेटा का अपना इंटरनल वर्शन बनाए रखता है. जब डेटा लिखा जाता है, तो उसे पहले इस लोकल वर्शन में लिखा जाता है. इसके बाद, Firebase क्लाइंट उस डेटा को रिमोट डेटाबेस सर्वर के साथ और अन्य क्लाइंट के साथ "बेहतर तरीके से" सिंक करता है.
इस वजह से, सर्वर पर कोई भी डेटा लिखे जाने से पहले, डेटाबेस में मौजूद सभी डेटा, लोकल इवेंट को ट्रिगर करता है. इसका मतलब है कि नेटवर्क इंतज़ार का समय या कनेक्टिविटी चाहे जो भी हो, आपका ऐप्लिकेशन रिस्पॉन्सिव बना रहता है.
कनेक्टिविटी फिर से इंस्टॉल होने के बाद, आपके ऐप्लिकेशन को इवेंट का सही सेट मिलता है. इससे क्लाइंट, सर्वर की मौजूदा स्थिति के साथ सिंक हो जाता है. इसके लिए, आपको कोई कस्टम कोड लिखने की ज़रूरत नहीं पड़ती.
ऑनलाइन और ऑफ़लाइन सुविधाओं के बारे में ज़्यादा जानें में, हम ऑफ़लाइन व्यवहार के बारे में ज़्यादा जानकारी देंगे.