Android पर डेटा पढ़ें और लिखें

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

यह दस्तावेज़ फायरबेस डेटा को पढ़ने और लिखने की मूल बातें शामिल करता है।

फायरबेस डेटा को FirebaseDatabase संदर्भ में लिखा जाता है और संदर्भ के लिए एक अतुल्यकालिक श्रोता को जोड़कर पुनर्प्राप्त किया जाता है। डेटा की प्रारंभिक स्थिति के लिए श्रोता को एक बार ट्रिगर किया जाता है और फिर कभी भी डेटा में परिवर्तन होता है।

(वैकल्पिक) फायरबेस लोकल एमुलेटर सूट के साथ प्रोटोटाइप और परीक्षण

आपका ऐप रीयलटाइम डेटाबेस से कैसे पढ़ता और लिखता है, इस बारे में बात करने से पहले, आइए टूल का एक सेट पेश करते हैं जिसका उपयोग आप प्रोटोटाइप और रियलटाइम डेटाबेस कार्यक्षमता का परीक्षण करने के लिए कर सकते हैं: फायरबेस लोकल एमुलेटर सूट। यदि आप अलग-अलग डेटा मॉडल आज़मा रहे हैं, अपने सुरक्षा नियमों का अनुकूलन कर रहे हैं, या बैक-एंड के साथ इंटरैक्ट करने का सबसे किफायती तरीका खोजने के लिए काम कर रहे हैं, तो लाइव सेवाओं को तैनात किए बिना स्थानीय रूप से काम करने में सक्षम होना एक अच्छा विचार हो सकता है।

एक रीयलटाइम डेटाबेस इम्यूलेटर लोकल इम्यूलेटर सूट का हिस्सा है, जो आपके ऐप को आपके एमुलेटेड डेटाबेस कंटेंट और कॉन्फ़िगरेशन के साथ-साथ वैकल्पिक रूप से आपके एमुलेटेड प्रोजेक्ट संसाधनों (फ़ंक्शंस, अन्य डेटाबेस और सुरक्षा नियम) के साथ इंटरैक्ट करने में सक्षम बनाता है।

रीयलटाइम डेटाबेस एम्यूलेटर का उपयोग करने में बस कुछ ही चरण शामिल हैं:

  1. एमुलेटर से कनेक्ट करने के लिए अपने ऐप के टेस्ट कॉन्फ़िगरेशन में कोड की एक पंक्ति जोड़ना।
  2. आपकी स्थानीय प्रोजेक्ट निर्देशिका की जड़ से, firebase emulators:start
  3. सामान्य रूप से रीयलटाइम डेटाबेस प्लेटफ़ॉर्म SDK का उपयोग करके या रीयलटाइम डेटाबेस REST API का उपयोग करके अपने ऐप के प्रोटोटाइप कोड से कॉल करना।

रीयलटाइम डेटाबेस और क्लाउड फ़ंक्शंस से संबंधित एक विस्तृत पूर्वाभ्यास उपलब्ध है। आपको स्थानीय इम्यूलेटर सुइट परिचय पर भी एक नज़र डालनी चाहिए।

डेटाबेस संदर्भ प्राप्त करें

डेटाबेस से डेटा पढ़ने या लिखने के लिए, आपको DatabaseReference का एक उदाहरण चाहिए:

Kotlin+KTX

private lateinit var database: DatabaseReference
// ...
database = Firebase.database.reference

Java

private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();

डेटा लिखें

मूल लेखन कार्य

मूल लेखन कार्यों के लिए, आप डेटा को निर्दिष्ट संदर्भ में सहेजने के लिए, उस पथ पर किसी भी मौजूदा डेटा को प्रतिस्थापित करने के लिए setValue() का उपयोग कर सकते हैं। आप इस विधि का उपयोग इसके लिए कर सकते हैं:

  • पास प्रकार जो उपलब्ध JSON प्रकारों के अनुरूप हैं:
    • String
    • Long
    • Double
    • Boolean
    • Map<String, Object>
    • List<Object>
  • एक कस्टम जावा ऑब्जेक्ट पास करें, यदि इसे परिभाषित करने वाली कक्षा में एक डिफ़ॉल्ट कन्स्ट्रक्टर है जो कोई तर्क नहीं लेता है और संपत्तियों को असाइन करने के लिए सार्वजनिक गेटर्स हैं।

यदि आप जावा ऑब्जेक्ट का उपयोग करते हैं, तो आपके ऑब्जेक्ट की सामग्री स्वचालित रूप से नेस्टेड फैशन में बाल स्थानों पर मैप की जाती है। जावा ऑब्जेक्ट का उपयोग करना भी आमतौर पर आपके कोड को अधिक पठनीय और बनाए रखने में आसान बनाता है। उदाहरण के लिए, यदि आपके पास मूल उपयोगकर्ता प्रोफ़ाइल वाला ऐप है, तो आपकी User वस्तु इस तरह दिख सकती है:

Kotlin+KTX

@IgnoreExtraProperties
data class User(val username: String? = null, val email: String? = null) {
    // Null default values create a no-argument default constructor, which is needed
    // for deserialization from a DataSnapshot.
}

Java

@IgnoreExtraProperties
public class User {

    public String username;
    public String email;

    public User() {
        // Default constructor required for calls to DataSnapshot.getValue(User.class)
    }

    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }

}

आप एक उपयोगकर्ता को setValue() के साथ निम्नानुसार जोड़ सकते हैं:

Kotlin+KTX

fun writeNewUser(userId: String, name: String, email: String) {
    val user = User(name, email)

    database.child("users").child(userId).setValue(user)
}

Java

public void writeNewUser(String userId, String name, String email) {
    User user = new User(name, email);

    mDatabase.child("users").child(userId).setValue(user);
}

इस तरह से setValue() का उपयोग निर्दिष्ट स्थान पर डेटा को अधिलेखित कर देता है, जिसमें कोई भी चाइल्ड नोड शामिल है। हालाँकि, आप अभी भी पूरे ऑब्जेक्ट को फिर से लिखे बिना बच्चे को अपडेट कर सकते हैं। यदि आप उपयोगकर्ताओं को अपनी प्रोफ़ाइल अपडेट करने की अनुमति देना चाहते हैं, तो आप उपयोगकर्ता नाम को निम्नानुसार अपडेट कर सकते हैं:

Kotlin+KTX

database.child("users").child(userId).child("username").setValue(name)

Java

mDatabase.child("users").child(userId).child("username").setValue(name);

डेटा पढ़ें

लगातार श्रोताओं के साथ डेटा पढ़ें

पथ पर डेटा पढ़ने और परिवर्तनों को सुनने के लिए, ValueEventListener को DatabaseReference में जोड़ने के लिए addValueEventListener() विधि का उपयोग करें।

श्रोता इवेंट कॉलबैक विशिष्ट उपयोग
ValueEventListener onDataChange() पथ की संपूर्ण सामग्री में परिवर्तनों को पढ़ें और सुनें।

आप किसी दिए गए पथ पर सामग्री के स्थिर स्नैपशॉट को पढ़ने के लिए onDataChange() विधि का उपयोग कर सकते हैं, क्योंकि वे घटना के समय मौजूद थे। यह विधि एक बार चालू हो जाती है जब श्रोता जुड़ा होता है और फिर से हर बार डेटा, बच्चों सहित, बदल जाता है। ईवेंट कॉलबैक एक स्नैपशॉट पारित किया जाता है जिसमें चाइल्ड डेटा सहित उस स्थान पर सभी डेटा होते हैं। यदि कोई डेटा नहीं है, तो जब आप exists() कॉल करते हैं और जब आप null getValue() कॉल करते हैं तो स्नैपशॉट false हो जाएगा।

निम्नलिखित उदाहरण डेटाबेस से एक पोस्ट के विवरण को पुनः प्राप्त करने वाले एक सामाजिक ब्लॉगिंग एप्लिकेशन को प्रदर्शित करता है:

Kotlin+KTX

val postListener = object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        // Get Post object and use the values to update the UI
        val post = dataSnapshot.getValue<Post>()
        // ...
    }

    override fun onCancelled(databaseError: DatabaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
    }
}
postReference.addValueEventListener(postListener)

Java

ValueEventListener postListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // Get Post object and use the values to update the UI
        Post post = dataSnapshot.getValue(Post.class);
        // ..
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
    }
};
mPostReference.addValueEventListener(postListener);

श्रोता एक डेटा DataSnapshot प्राप्त करता है जिसमें घटना के समय डेटाबेस में निर्दिष्ट स्थान पर डेटा होता है। स्नैपशॉट पर getValue() को कॉल करने से डेटा का जावा ऑब्जेक्ट प्रतिनिधित्व होता है। यदि स्थान पर कोई डेटा मौजूद नहीं है, तो getValue() को कॉल करना null हो जाता है।

इस उदाहरण में, ValueEventListener onCancelled() मेथड को भी परिभाषित करता है जिसे रीड कैंसिल होने पर कॉल किया जाता है। उदाहरण के लिए, यदि क्लाइंट के पास फायरबेस डेटाबेस स्थान से पढ़ने की अनुमति नहीं है, तो एक रीड को रद्द किया जा सकता है। यह विधि DatabaseError एरर ऑब्जेक्ट पारित करती है जो इंगित करती है कि विफलता क्यों हुई।

एक बार डेटा पढ़ें

get() का उपयोग करके एक बार पढ़ें

एसडीके को डेटाबेस सर्वर के साथ इंटरैक्शन प्रबंधित करने के लिए डिज़ाइन किया गया है, चाहे आपका ऐप ऑनलाइन हो या ऑफलाइन।

आमतौर पर, आपको बैकएंड से डेटा के अपडेट की सूचना प्राप्त करने के लिए डेटा पढ़ने के लिए ऊपर वर्णित ValueEventListener तकनीकों का उपयोग करना चाहिए। श्रोता तकनीकें आपके उपयोग और बिलिंग को कम करती हैं, और आपके उपयोगकर्ताओं को ऑनलाइन और ऑफ़लाइन होने पर सर्वोत्तम अनुभव देने के लिए अनुकूलित होती हैं।

यदि आपको केवल एक बार डेटा की आवश्यकता है, तो आप डेटाबेस से डेटा का स्नैपशॉट प्राप्त करने के लिए get() का उपयोग कर सकते हैं। यदि किसी भी कारण get() सर्वर मान वापस करने में असमर्थ है, तो क्लाइंट स्थानीय संग्रहण कैश की जांच करेगा और यदि मान अभी भी नहीं मिला है तो एक त्रुटि लौटाएगा।

गेट get() का अनावश्यक उपयोग बैंडविड्थ के उपयोग को बढ़ा सकता है और प्रदर्शन के नुकसान का कारण बन सकता है, जिसे ऊपर दिखाए गए रीयलटाइम श्रोता का उपयोग करके रोका जा सकता है।

Kotlin+KTX

mDatabase.child("users").child(userId).get().addOnSuccessListener {
    Log.i("firebase", "Got value ${it.value}")
}.addOnFailureListener{
    Log.e("firebase", "Error getting data", it)
}

Java

mDatabase.child("users").child(userId).get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DataSnapshot> task) {
        if (!task.isSuccessful()) {
            Log.e("firebase", "Error getting data", task.getException());
        }
        else {
            Log.d("firebase", String.valueOf(task.getResult().getValue()));
        }
    }
});

एक बार श्रोता का उपयोग करके पढ़ें

कुछ मामलों में आप चाहते हैं कि सर्वर पर अपडेट किए गए मान की जांच करने के बजाय स्थानीय कैश से मान तुरंत लौटाया जाए। उन मामलों में आप तुरंत स्थानीय डिस्क कैश से डेटा प्राप्त करने के लिए addListenerForSingleValueEvent का उपयोग कर सकते हैं।

यह उस डेटा के लिए उपयोगी है जिसे केवल एक बार लोड करने की आवश्यकता होती है और जिसके बार-बार बदलने या सक्रिय रूप से सुनने की आवश्यकता नहीं होती है। उदाहरण के लिए, पिछले उदाहरणों में ब्लॉगिंग ऐप उपयोगकर्ता के प्रोफ़ाइल को लोड करने के लिए इस विधि का उपयोग करता है जब वे एक नई पोस्ट लिखना शुरू करते हैं।

डेटा को अपडेट करना या हटाना

विशिष्ट क्षेत्रों को अद्यतन करें

अन्य चाइल्ड नोड्स को अधिलेखित किए बिना एक नोड के विशिष्ट बच्चों को एक साथ लिखने के लिए, updateChildren() विधि का उपयोग करें।

updateChildren() को कॉल करते समय, आप कुंजी के लिए पथ निर्दिष्ट करके निचले स्तर के बाल मानों को अपडेट कर सकते हैं। यदि डेटा को बेहतर पैमाने पर रखने के लिए कई स्थानों पर संग्रहीत किया जाता है, तो आप डेटा फैन-आउट का उपयोग करके उस डेटा के सभी उदाहरणों को अपडेट कर सकते हैं। उदाहरण के लिए, एक सोशल ब्लॉगिंग ऐप में इस तरह की एक Post क्लास हो सकती है:

Kotlin+KTX

@IgnoreExtraProperties
data class Post(
    var uid: String? = "",
    var author: String? = "",
    var title: String? = "",
    var body: String? = "",
    var starCount: Int = 0,
    var stars: MutableMap<String, Boolean> = HashMap()
) {

    @Exclude
    fun toMap(): Map<String, Any?> {
        return mapOf(
                "uid" to uid,
                "author" to author,
                "title" to title,
                "body" to body,
                "starCount" to starCount,
                "stars" to stars
        )
    }
}

Java

@IgnoreExtraProperties
public class Post {

    public String uid;
    public String author;
    public String title;
    public String body;
    public int starCount = 0;
    public Map<String, Boolean> stars = new HashMap<>();

    public Post() {
        // Default constructor required for calls to DataSnapshot.getValue(Post.class)
    }

    public Post(String uid, String author, String title, String body) {
        this.uid = uid;
        this.author = author;
        this.title = title;
        this.body = body;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("uid", uid);
        result.put("author", author);
        result.put("title", title);
        result.put("body", body);
        result.put("starCount", starCount);
        result.put("stars", stars);

        return result;
    }
}

एक पोस्ट बनाने के लिए और साथ ही इसे हाल की गतिविधि फ़ीड और पोस्टिंग उपयोगकर्ता की गतिविधि फ़ीड में अपडेट करने के लिए, ब्लॉगिंग एप्लिकेशन इस तरह के कोड का उपयोग करता है:

Kotlin+KTX

private fun writeNewPost(userId: String, username: String, title: String, body: String) {
    // Create new post at /user-posts/$userid/$postid and at
    // /posts/$postid simultaneously
    val key = database.child("posts").push().key
    if (key == null) {
        Log.w(TAG, "Couldn't get push key for posts")
        return
    }

    val post = Post(userId, username, title, body)
    val postValues = post.toMap()

    val childUpdates = hashMapOf<String, Any>(
            "/posts/$key" to postValues,
            "/user-posts/$userId/$key" to postValues
    )

    database.updateChildren(childUpdates)
}

Java

private void writeNewPost(String userId, String username, String title, String body) {
    // Create new post at /user-posts/$userid/$postid and at
    // /posts/$postid simultaneously
    String key = mDatabase.child("posts").push().getKey();
    Post post = new Post(userId, username, title, body);
    Map<String, Object> postValues = post.toMap();

    Map<String, Object> childUpdates = new HashMap<>();
    childUpdates.put("/posts/" + key, postValues);
    childUpdates.put("/user-posts/" + userId + "/" + key, postValues);

    mDatabase.updateChildren(childUpdates);
}

यह उदाहरण /posts/$postid postid पर सभी उपयोगकर्ताओं के लिए पोस्ट वाले नोड में एक पोस्ट बनाने के लिए push() का उपयोग करता है और साथ ही getKey() के साथ कुंजी को पुनः प्राप्त करता है। तब कुंजी का उपयोग उपयोगकर्ता के पोस्ट में /user-posts/$userid/$postid पर दूसरी प्रविष्टि बनाने के लिए किया जा सकता है।

इन रास्तों का उपयोग करके, आप JSON ट्री में एक ही कॉल के साथ JSON ट्री में कई स्थानों पर एक साथ अपडेट कर सकते हैं updateChildren() , जैसे कि यह उदाहरण दोनों स्थानों में नई पोस्ट कैसे बनाता है। इस तरह से किए गए एक साथ अद्यतन परमाणु हैं: या तो सभी अद्यतन सफल होते हैं या सभी अद्यतन विफल होते हैं।

एक पूर्णता कॉलबैक जोड़ें

यदि आप जानना चाहते हैं कि आपका डेटा कब प्रतिबद्ध किया गया है, तो आप एक पूर्ण श्रोता जोड़ सकते हैं। दोनों setValue() और updateChildren() एक वैकल्पिक समापन श्रोता लेते हैं जिसे तब कहा जाता है जब लेखन को डेटाबेस में सफलतापूर्वक सबमिट किया गया हो। यदि कॉल असफल होती है, तो श्रोता को एक एरर ऑब्जेक्ट पास किया जाता है जो दर्शाता है कि विफलता क्यों हुई।

Kotlin+KTX

database.child("users").child(userId).setValue(user)
        .addOnSuccessListener {
            // Write was successful!
            // ...
        }
        .addOnFailureListener {
            // Write failed
            // ...
        }

Java

mDatabase.child("users").child(userId).setValue(user)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                // Write was successful!
                // ...
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Write failed
                // ...
            }
        });

डेटा हटाएं

डेटा को हटाने का सबसे सरल तरीका उस डेटा के स्थान के संदर्भ में removeValue() को कॉल करना है।

आप किसी अन्य लेखन ऑपरेशन जैसे setValue() या updateChildren() के मान के रूप में null निर्दिष्ट करके भी हटा सकते हैं। आप एक एपीआई कॉल में कई बच्चों को हटाने के लिए इस तकनीक का उपयोग updateChildren() के साथ कर सकते हैं।

श्रोताओं को अलग करें

आपके फायरबेस डेटाबेस संदर्भ पर removeEventListener() विधि को कॉल करके कॉलबैक हटा दिए जाते हैं।

यदि एक श्रोता को डेटा स्थान पर कई बार जोड़ा गया है, तो इसे प्रत्येक घटना के लिए कई बार कहा जाता है, और इसे पूरी तरह से हटाने के लिए आपको इसे समान संख्या में अलग करना होगा।

पेरेंट श्रोता पर removeEventListener() को कॉल करने से उसके चाइल्ड नोड्स पर पंजीकृत श्रोता स्वचालित रूप से नहीं हटते हैं; कॉलबैक को हटाने के लिए किसी भी बाल श्रोताओं पर removeEventListener() को भी कॉल किया जाना चाहिए।

डेटा को लेनदेन के रूप में सहेजें

डेटा के साथ काम करते समय जो समवर्ती संशोधनों, जैसे वृद्धिशील काउंटरों द्वारा दूषित हो सकता है, आप लेनदेन ऑपरेशन का उपयोग कर सकते हैं। आप इस ऑपरेशन को दो तर्क देते हैं: एक अपडेट फ़ंक्शन और एक वैकल्पिक पूर्णता कॉलबैक। अपडेट फ़ंक्शन डेटा की वर्तमान स्थिति को एक तर्क के रूप में लेता है और नई वांछित स्थिति देता है जिसे आप लिखना चाहते हैं। यदि कोई अन्य क्लाइंट आपके नए मान के सफलतापूर्वक लिखे जाने से पहले स्थान पर लिखता है, तो आपके अपडेट फ़ंक्शन को नए वर्तमान मान के साथ फिर से कॉल किया जाता है, और लिखने का पुनः प्रयास किया जाता है।

उदाहरण के लिए, उदाहरण के लिए सोशल ब्लॉगिंग ऐप में, आप उपयोगकर्ताओं को पोस्ट को तारांकित और अतारांकित करने की अनुमति दे सकते हैं और ट्रैक कर सकते हैं कि किसी पोस्ट को कितने सितारे प्राप्त हुए हैं:

Kotlin+KTX

private fun onStarClicked(postRef: DatabaseReference) {
    // ...
    postRef.runTransaction(object : Transaction.Handler {
        override fun doTransaction(mutableData: MutableData): Transaction.Result {
            val p = mutableData.getValue(Post::class.java)
                    ?: return Transaction.success(mutableData)

            if (p.stars.containsKey(uid)) {
                // Unstar the post and remove self from stars
                p.starCount = p.starCount - 1
                p.stars.remove(uid)
            } else {
                // Star the post and add self to stars
                p.starCount = p.starCount + 1
                p.stars[uid] = true
            }

            // Set value and report transaction success
            mutableData.value = p
            return Transaction.success(mutableData)
        }

        override fun onComplete(
                databaseError: DatabaseError?,
                committed: Boolean,
                currentData: DataSnapshot?
        ) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError!!)
        }
    })
}

Java

private void onStarClicked(DatabaseReference postRef) {
    postRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Post p = mutableData.getValue(Post.class);
            if (p == null) {
                return Transaction.success(mutableData);
            }

            if (p.stars.containsKey(getUid())) {
                // Unstar the post and remove self from stars
                p.starCount = p.starCount - 1;
                p.stars.remove(getUid());
            } else {
                // Star the post and add self to stars
                p.starCount = p.starCount + 1;
                p.stars.put(getUid(), true);
            }

            // Set value and report transaction success
            mutableData.setValue(p);
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean committed,
                               DataSnapshot currentData) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
        }
    });
}

लेन-देन का उपयोग करना स्टार काउंट को गलत होने से रोकता है यदि कई उपयोगकर्ता एक ही पोस्ट को एक ही समय में स्टार करते हैं या क्लाइंट के पास पुराना डेटा है। यदि लेन-देन अस्वीकार कर दिया जाता है, तो सर्वर क्लाइंट को वर्तमान मान लौटाता है, जो अद्यतन मूल्य के साथ लेनदेन को फिर से चलाता है। यह तब तक दोहराता है जब तक लेन-देन स्वीकार नहीं किया जाता या बहुत अधिक प्रयास नहीं किए जाते।

परमाणु सर्वर-साइड वेतन वृद्धि

उपरोक्त उपयोग के मामले में हम डेटाबेस के लिए दो मान लिख रहे हैं: उस उपयोगकर्ता की आईडी जो पोस्ट को स्टार/अनस्टार करता है, और बढ़ी हुई स्टार गिनती। अगर हम पहले से ही जानते हैं कि उपयोगकर्ता पोस्ट को तारांकित कर रहा है, तो हम लेन-देन के बजाय परमाणु वृद्धि ऑपरेशन का उपयोग कर सकते हैं।

Kotlin+KTX

private fun onStarClicked(uid: String, key: String) {
    val updates: MutableMap<String, Any> = hashMapOf(
        "posts/$key/stars/$uid" to true,
        "posts/$key/starCount" to ServerValue.increment(1),
        "user-posts/$uid/$key/stars/$uid" to true,
        "user-posts/$uid/$key/starCount" to ServerValue.increment(1)
    )
    database.updateChildren(updates)
}

Java

private void onStarClicked(String uid, String key) {
    Map<String, Object> updates = new HashMap<>();
    updates.put("posts/"+key+"/stars/"+uid, true);
    updates.put("posts/"+key+"/starCount", ServerValue.increment(1));
    updates.put("user-posts/"+uid+"/"+key+"/stars/"+uid, true);
    updates.put("user-posts/"+uid+"/"+key+"/starCount", ServerValue.increment(1));
    mDatabase.updateChildren(updates);
}

यह कोड एक लेन-देन ऑपरेशन का उपयोग नहीं करता है, इसलिए यदि कोई परस्पर विरोधी अपडेट है तो यह स्वचालित रूप से फिर से नहीं चलता है। हालाँकि, चूंकि इंक्रीमेंट ऑपरेशन सीधे डेटाबेस सर्वर पर होता है, इसलिए विरोध की कोई संभावना नहीं है।

यदि आप एप्लिकेशन-विशिष्ट विरोधों का पता लगाना और उन्हें अस्वीकार करना चाहते हैं, जैसे कि कोई उपयोगकर्ता किसी ऐसी पोस्ट को तारांकित करता है जिसे वे पहले ही तारांकित कर चुके हैं, तो आपको उस उपयोग मामले के लिए कस्टम सुरक्षा नियम लिखने चाहिए।

डेटा के साथ ऑफ़लाइन काम करें

यदि कोई क्लाइंट अपना नेटवर्क कनेक्शन खो देता है, तो आपका ऐप ठीक से काम करना जारी रखेगा।

फायरबेस डेटाबेस से जुड़ा प्रत्येक क्लाइंट किसी भी डेटा का अपना आंतरिक संस्करण रखता है, जिस पर श्रोताओं का उपयोग किया जा रहा है या जिसे सर्वर के साथ सिंक में रखने के लिए फ़्लैग किया गया है। जब डेटा पढ़ा या लिखा जाता है, तो डेटा के इस स्थानीय संस्करण का पहले उपयोग किया जाता है। फायरबेस क्लाइंट तब उस डेटा को दूरस्थ डेटाबेस सर्वर और अन्य क्लाइंट के साथ "सर्वश्रेष्ठ-प्रयास" के आधार पर सिंक्रनाइज़ करता है।

नतीजतन, सर्वर के साथ किसी भी बातचीत से पहले, सभी डेटाबेस को लिखते हैं, तुरंत स्थानीय घटनाओं को ट्रिगर करते हैं। इसका मतलब है कि आपका ऐप नेटवर्क विलंबता या कनेक्टिविटी की परवाह किए बिना उत्तरदायी बना रहता है।

एक बार कनेक्टिविटी फिर से स्थापित हो जाने के बाद, आपके ऐप को ईवेंट का उपयुक्त सेट प्राप्त होता है ताकि क्लाइंट बिना किसी कस्टम कोड को लिखे वर्तमान सर्वर स्थिति के साथ सिंक हो सके।

हम ऑनलाइन और ऑफ़लाइन क्षमताओं के बारे में और जानें में ऑफ़लाइन व्यवहार के बारे में और बात करेंगे.

अगले कदम