2016-12-07 8 views
14

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

प्रश्न निर्दिष्ट करने के लिए, आइए कल्पना करें कि हमारे पास हैकरन्यूज फ़ीड है, और हम उदाहरण सुनते हैं। फायरबेस में "पोस्ट" ऑब्जेक्ट।

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

हम दो श्रोताओं के रूप में मैं उल्लेख किया है, सवाल यह है कि जो बेहतर है?

जब हम ValueEventListener का उपयोग करते हैं तो हमें पूरा संग्रह मिल जाएगा, लेकिन किसी भी बदलाव के मामले में, जैसे एक उपयोगकर्ता ने पोस्ट की सामग्री बदल दी है, हमें पूरे डेटा को फिर से लोड करना होगा, जिसका अर्थ है महंगे नेटवर्क स्थानांतरण के माध्यम से अधिक बाइट भेजना। एक और समस्या है जब हम उपयोगकर्ता multilisteners है, और यहाँ उदाहरण है:

  • पोस्ट userId है, लेकिन हम उसके नाम प्रदर्शित करना चाहते हैं, तो onDataChanged विधि में हम उपयोगकर्ता डेटा लाने की है, इस तरह:

    postsReference.addValueEventListener(new ValueEventListener() { 
        @Override 
        public void onDataChange(DataSnapshot dataSnapshot) { 
          for (DataSnapshot data : dataSnapshot.getChildren()) { 
           Post post = data.getValue(Post.class); 
           usersReference.child(post.getUserId()).addListenerForSingleValueEvent(new ValueEventListener() { 
    
             @Override 
             public void onDataChange(DataSnapshot dataSnapshot) { 
              // Here we have user data 
             } 
    
             @Override 
             public void onCancelled(FirebaseError firebaseError) { 
    
             } 
           }); 
          } 
        } 
    
        @Override 
        public void onCancelled(FirebaseError firebaseError) { 
        } 
    }); 
    

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

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

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

प्रश्न

की तुलना में मैं ऊपर लिखा था क्या संग्रह के साथ firebase उपयोग की सर्वोत्तम प्रथाएँ, और शायद बेहतर समाधान कर रहे हैं?

संपादित

डाटा योजना इस प्रकार दिखाई देगा:

"posts" : { 
    "123456" : { 
     "createdAt" : 1478696885622, 
     "content" : "This is post content", 
     "title" : "This is post title", 
     "userId" : "abc" 
    }, 
    "789012" : { 
     "createdAt" : 1478696885622, 
     "content" : "This is post content 2", 
     "title" : "This is post title 2", 
     "userId" : "efg" 
    } 
    } 
    "users" : { 
    "abc" : { 
     "name" : "username1" 
    }, 
    "efg" : { 
     "name" : "username2" 
    } 
    } 

संपादित 2

मैं एक गलती की है -> Firebase ValueEventListener में पूरे डेटा प्राप्त करने में नहीं है जब कुछ है बदला हुआ। यह केवल "डेल्टा" प्राप्त होता है, here सबूत है।

+0

तुम मुझे अपना डेटाबेस स्कीमा दिखा सकते हैं? –

+0

मैंने प्रश्न संपादित किया। – ThirdMartian

+0

आपने इनमें से कोई भी उल्लेख नहीं किया है। फायरबेस रीसाइक्लर एडाप्टर [फायरबेस यूआई] से (https: // github।कॉम/फायरबेस/फायरबेस ईआई-एंड्रॉइड) इस स्थिति में सबसे अच्छा है –

उत्तर

2

जब Firebase पर संग्रह डेटा के साथ काम कर आप का उपयोग करना चाहिए:

  • onChildAdded
  • onChildChanged
  • onChildRemoved
  • onChildMoved

आप इन लेकिन मैं के सभी की आवश्यकता नहीं होती पाया गया है कि आमतौर पर onChildAdded और onChildRemoved अक्सर आवश्यक हैं। आपको अपने एडाप्टर में बदल रहे डेटा को सॉर्ट करना और ट्रैक करना होगा और उसे प्रत्येक अपडेट किए गए बच्चे पर रीसाइक्लर व्यू पर वापस भेजना होगा।

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

Source

+0

कृपया मेरा संपादन 2 – ThirdMartian

+0

देखें फ़ायरबेस पूरे डेटा स्नैपशॉट को वापस कर देगा जहां आपका 'ValueEventListener' संलग्न होता है जब भी कोई बच्चा बदल जाता है। [स्रोत] (https://firebase.google.com/docs/database/android/read-and-write#listen_for_value_events) –

+0

हाँ, लेकिन यह इसे पूरी तरह से डाउनलोड नहीं करेगा, मुझे बस संपूर्ण डेटा स्नैपशॉट मिलेगा लेकिन डेटाबेस आंतरिक रूप से केवल "डेल्टा" – ThirdMartian

12

इस सवाल में कई चिंताओं (अर्थात् प्रदर्शन, प्रगति संकेतक, इस तरह उन्हें छँटाई के रूप में नए डेटा को संभालने) कर रहे हैं। स्वाभाविक रूप से आपको ऐसे समाधान के साथ आना चाहिए जो आपकी आवश्यकताओं की प्राथमिकता को ध्यान में रखे। IMO ValueEventListener और ChildEventListener दोनों अपने उपयोग के मामलों है:

  1. ChildEventListener आम तौर पर वस्तुओं की सूची sync'ing की सिफारिश की तरीका है। यह भी documentation on working with lists में बताया गया है:

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

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

  2. ValueEventListener अधिक उपयोगी हो सकता है जब आपको बच्चे के संशोधन पर पूरी सूची को संसाधित करने की आवश्यकता होती है। यह वह मामला है जब आपको अपनी RecyclerView में सूची को सॉर्ट करना होगा। पूरी सूची प्राप्त करके, इसे सॉर्ट करना और दृश्य के डेटा सेट को रीफ्रेश करके ऐसा करना अधिक आसान है। दूसरी तरफ, ChildEventListener का उपयोग करके, सॉर्टिंग करना अधिक कठिन होता है क्योंकि आपके पास केवल प्रति अपडेट ईवेंट सूची में एक विशिष्ट बच्चे तक पहुंच है।

एक प्रदर्शन दृष्टि से

, यह देखते हुए कि यहां तक ​​कि ValueEventListener "डेल्टा" जबकि अद्यतन sync'ing, मैं केवल क्लाइंट की तरफ कम कुशल के रूप में यह सोचने के लिए जाते हैं के बारे में पता है, क्योंकि ग्राहक को पूरी सूची में प्रसंस्करण करना है, लेकिन नेटवर्क पक्ष में अक्षमता होने से यह अभी भी बेहतर है।

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

// show progress indicator 
postsReference.addListenerForSingleValueEvent(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     // load initial data set 
     // hide progress indicator when done loading 
    } 

    ... 
}); 
2

मैं anyday इस मामले में onchildAdded श्रोता का प्रयोग करेंगे, वहाँ यह करने के कई फायदे हैं, सबसे पहले आप नेटवर्क पता लगा है ऑपरेशन है कि मान लीजिए कि 100 पद हैं और यहां तक ​​कि अगर कोई बदल जाता है तो भी आप उन सभी का कॉलबैक प्राप्त करेंगे। जबकि चाइल्डलिस्टर में आपको एकमात्र पोस्ट का कॉलबैक मिलेगा जो बदल गया है। तो क्या आप कर सकते हैं की तरह इस :: recycler विचारों के तरीकों के साथ firebase की कॉलबैक नक्शा है -

onChildAdded -> आप अपने वर्ग में dataSnap डाली और recyclerView.notifyItemAdded()

onChildRemoved कॉल करना होगा - -> recyclerView.notifyItemRemoved (int)

onChildChanged -> recyclerView.notifyItemChanged (int)

onChildMoved -> (आप शायद इस की जरूरत नहीं है, यह आदेश/वरीयता के लिए है)

3

मैंने लिया वही सटीक समस्या (एंड्रॉइड में RecyclerView के लिए ValueEventListener बनाम ChildEventListener)। एक firebase db स्थान है जहाँ मेरे पदों हैं

मान लीजिए dbref अंक:

समाधान मैं इस्तेमाल किया दोनों इस तरह से गठबंधन करने के लिए किया गया था।

  1. उपयोग वेल (ValueEventListener) dbref पर मौजूदा डेटा की सूची के साथ recyclerview को भरने के लिए। कुछ इस तरह: vel = dbref.addValueEventListener(vel);
  2. एक बार मैं dbref पर मौजूदा डेटा की सूची है, मैं श्रोता वेलसे dbref निकालें: dbref.removeEventListener(vel);। यह आवश्यक हो तो आपने चरण 1
  3. में dbref.addListenerForSingleValueEvent(vel); इस्तेमाल किया एक क्वेरी क्वेरी लिखें अब से dbref पर डाला नई पोस्ट फिल्टर करने के लिए नहीं है। कुछ इस तरह: query = dbref.orderByChild(post.createdat).startAt(System.currentTimeMillis())
  4. क्वेरी करने के लिए एक सेल (ChildEventListener) संलग्न केवल नए पोस्ट प्राप्त करने के लिए: query.addChildEventListener(cel);
संबंधित मुद्दे