2015-09-02 19 views
7

मुझे notifyItemMoved() विधि का उपयोग करने में कोई समस्या है। ऐसा लगता है कि अप्रचलित विचारों को गलत तरीके से प्रदर्शित किया जा रहा है।रीसाइक्लर देखें भ्रष्टाचार का उपयोग करके देखें भ्रष्ट देखें()

मेरी सूची में इसमें 4 तत्व हैं। मैं क्या करना चाहता हूं आइटम 1 और आइटम 3 के बीच एक स्वैप एनिमेट कर रहा है। आइटम 1 और 3 सही ढंग से स्वैप करें, लेकिन आइटम 2 आइटम 3 पर क्या दिखाता है!

तो सूची से शुरू होता है कुछ इस तरह की तलाश में:

Item 0 
Item 1 
Item 2 
Item 3 

और इस तरह समाप्त होता है:

Item 0 
Item 3 
Item 3 <!-- What the heck has this changed for? 
Item 1 

मेरे अनुकूलक एक List mProductList द्वारा समर्थित है।

public void sortBackingListUsingSortingList(List<ProductWrapper> newProductItems) { 
    Log.e("", "Before:"); 
    for(ProductWrapper wrapper : mProductItems) wrapper.log(); 
    for(int i = 0; i < newProductItems.size(); i++) { 
     ProductWrapper currentItem = mProductItems.get(i); 
     ProductWrapper correctItem = newProductItems.get(i); 

     if(!currentItem.equals(correctItem)) { 
      // Item in wrong place 
      int indexOfCorrectItem = getIndexOfItemInList(mProductItems, correctItem); 
      Collections.swap(mProductItems, i, indexOfCorrectItem); 
      notifyItemMoved(i, indexOfCorrectItem); 
      Log.e("", "notifyItemMoved(" + i + ", " + indexOfCorrectItem+")"); 
      Log.e("", "After:"); 
      for(ProductWrapper wrapper : mProductItems) wrapper.log(); 
     } 
    } 
} 

मैं भी अगर मेरे विचार तर्क बुलाया जा रहा है onBindViewHolder को प्रवेश करने की जांच में शामिल किया है::

@Override 
public void onBindViewHolder(HolderBasic holder, int position) { 
    Log.e("", "onBindViewHolder(holder, " + position + ")"); 
    holder.fill(mProductItems.get(position)); 
} 

मेरे लॉग इस तरह दिखेगा:

09-02 14:39:17.853 ﹕ Before: 
09-02 14:39:17.853 : Item 0 
09-02 14:39:17.853 : Item 1 
09-02 14:39:17.853 : Item 2 
09-02 14:39:17.853 : Item 3 

09-02 14:39:17.854 ﹕ notifyItemMoved(1, 3) 

09-02 14:39:17.854 ﹕ After: 
09-02 14:39:17.854 : Item 0 
09-02 14:39:17.854 : Item 3 
09-02 14:39:17.854 : Item 2 
09-02 14:39:17.854 : Item 1 

09-02 14:39:17.867 ﹕ onBindViewHolder(holder, 1) 
09-02 14:39:17.874 ﹕ onBindViewHolder(holder, 3) 
मैं निम्नलिखित कोड फोन

जैसा कि आप देख सकते हैं, आइटम 2 को इसके प्रदर्शन को बदलने के लिए कोई कारण नहीं है - और फिर भी, यह करता है। किसी को पता है क्यों?

संपादित

मैं पूरी एडाप्टर के माध्यम से पाशन और हर आइटम पर notifyItemChanged() फोन करके ऊपर मिल सकता है। अक्षम और अच्छा समाधान नहीं, लेकिन उपयोगकर्ता के लिए अदृश्य है।

+0

तो, मुझे लगता है कि आप कह रहे हैं कि 'ऑनबिंडव्यूहोल्डर (धारक, 1)' नहीं कहा जाना चाहिए, है ना? मुझे यह भी नहीं पता कि यह क्यों * कहा जाता है ... लेकिन मुझे यह भी लगता है कि आपको केवल 'सूचित करें' इटैम चेंज (i); सूचित करें ItemChanged (indexOfCorrectItem); '' सूचित करने के बजाय इसे हटाएं (i, indexOfCorrectItem); 'क्या आपने कोशिश की है? –

+0

नहीं, समस्या यह है कि आइटम 2 इसके प्रदर्शन को बदल रहा है। onBindViewHolder को 1 और 3 के लिए बुलाया जाना चाहिए क्योंकि सूचित करें IememMoved (1, 3) उनमें से दोनों को फिर से खींचा जाने की आवश्यकता है। क्या नहीं होना चाहिए आइटम 2 किसी भी तरह से शामिल होना चाहिए, इसे छुआ नहीं जाना चाहिए। – Graeme

+0

मुझे नहीं पता कि RecyclerView सही तरीके से क्यों व्यवहार कर रहा है, लेकिन मैं * समझ सकता हूं कि यह आपके द्वारा किए जा रहे कार्यों से उलझन में है: आपने '0, 1, 2, 3]' से शुरू किया था। 'NotifyItemChanged (1, 3)' को कॉल करके आप कह रहे हैं: "मैंने आइटम स्थिति 1 को स्थिति 3 पर डाला है"। यह सच होने के लिए आपकी सूची अब '[0, 2, 3, 1]' होनी चाहिए। लेकिन यह वास्तव में '[0, 3, 2, 1] 'है, इसलिए यदि यह' ऑनबिंड व्यूहोल्डर (धारक, 1)' * निश्चित रूप से कॉल करता है * यह वहां '3' को देखने जा रहा है और '2' को ओवरराइट कर रहा है पहले वहाँ था मुझे कौन सा पहेली केवल इतना है कि इसे कॉल करने की आवश्यकता महसूस होती है ... –

उत्तर

12

@ david.mihola के लिए धन्यवाद जो मुझे गलत करने के लिए अग्रणी है।

यह पता लगाने में इतनी देर लग गई क्योंकि लक्षण ने समस्या को स्पष्ट नहीं किया!

मैं यह कर रहा था:

Collections.swap(mProductItems, i, indexOfCorrectItem); 
notifyItemMoved(i, indexOfCorrectItem) 

लेकिन, मुझे स्पष्ट रूप से क्या notifyItemMoved() वास्तव में क्या कर रहा था के माध्यम से नहीं सोचा था। यह केवल एडाप्टर को सूचित कर रहा है कि आइटम iindexOfCorrectItemपर ले जाया गया है, यह एडाप्टर को नहीं बता रहा है कि indexOfCorrectItem भी i पर स्थानांतरित हो गया है।

  1. ले जाएँ आइटम 1 से 3
  2. ले जाएँ क्या 1 से 2 पर था खाई
  3. ले जाएँ क्या 2 से 3 पर था भरने के लिए भरने के लिए:

    कवर के तहत यह निम्न कर रहा था खाई

  4. notifyItemChanged(1);
  5. notifyItemChanged(3);

बेशक उपरोक्त आइटम आइटम को बिना किसी ताज़ा दृश्य के आइटम 2 पर ले जाया गया है! यह चरण 4 और 5 था जो आइटम 1 और आइटम 3 को सही तरीके से प्रदर्शित करके समस्या को छुपा रहे थे और आइटम 2 को गलत छोड़कर!

जैसे ही मैं इस एहसास हुआ के रूप में मैं निम्नलिखित कोड की कोशिश की:

notifyItemMoved(indexOfCorrectItem, i); 
notifyItemMoved(i, indexOfCorrectItem); 

यह सही क्रम में सूची को छोड़ दिया है, लेकिन यह कम एनीमेशन circuited।

mProductItems.remove(indexOfCorrectItem); 
mProductItems.add(i, correctItem); 
notifyItemMoved(indexOfCorrectItem, i); 
+0

पूरी तरह से स्पष्टीकरण के लिए धन्यवाद: क्या आपने यह समझने के लिए पर्याप्त रीसाइक्लर व्यू कोड देखा है कि इटैम चेंज (1) को क्यों कॉल किया गया था (आपका चरण 4)? यदि आप एडाप्टर को बताते हैं "आइटम 1 हटा दिया गया है, तो एक स्लॉट के नीचे आइटम 2 स्लाइड करें" इसे उस आइटम को बिल्कुल पुनर्निर्मित करने की आवश्यकता नहीं है। कम से कम इसके बाद किसी भी आइटम को अगले आइटम को पुन: स्थापित करने की आवश्यकता नहीं होगी ... –

+0

मैंने पाया कि 'संग्रह का उपयोग करना।स्वैप (डेटासेट, सेशन, टोपीशन); सूचित करें ItemMoved (सेशन, toPosition); सूचित करें ItemChanged (सेशन); सूचित करें ItemChanged (toPosition); ' दोनों एनिमेशन को रखा, और किसी भी गलत दृश्य धारक बाइंडिंग को अपडेट किया जो पुरानी स्थिति मान – saganaut

+0

का उपयोग करता था, आइटमों के मानों को अपडेट करने का प्रयास करते समय मुझे एक ही समस्या थी। मेरा रीसाइक्लिंगव्यू डुप्लिकेट/कॉर्रॉम्प्टेड आइटम दिखा रहा था, जबकि एडाप्टर की सही जानकारी थी, इसलिए समस्या रीसाइक्लिंगव्यू में थी, एडाप्टर नहीं। मुझे @Graeme जैसा ही करना था। धन्यवाद। item.setCantidad (item.getCantidad() + newItem.getCantidad()); mitems.remove (स्थिति); mitems.add (आइटम); सूचित करें ItemMoved (स्थिति, mitems.size() - 1); सूचित करें ItemChanged (mitems.size() - 1); – Herman

1

मैं एक ही मुद्दा था:

तो, बजाय, मैं पूरी तरह से अदला-बदली फेंक दिया। रीसाइक्लिंग व्यू-आइटम ड्रैग & ड्रॉप पर दूषित हैं। लेकिन मैं एक सरल समाधान मिल गया है: अपने RecyclerView.Adapter.class में निम्नलिखित

@Override 
public long getItemId(int position) { 
    // here code for getting the right itemID, 
    // i.e. return super.getItemId(mPosition); 
    // where mPosition ist the Position in the Collection. 
} 

आप स्थिति के लिए सही Itemid लौटना चाहिए है सुनिश्चित करें। अब से आइटम भ्रष्ट नहीं हैं।

0

एक खींचें & ड्रॉप के बाद अपने मद की वास्तविक स्थिति के लिए, अपना एडाप्टर के लिए इस पद्धति जोड़ें:

private int getItemPosition(Item item){ // (<-- replace with your item) 
    int i = 0; 
    // (replace with your items and methods here) 
    for (Item currentItem : mItems) { 
     if (currentItem.getItemId() == item.getItemId()) break; 
     i++; 
    } 
    return i; 
} 

और स्थिति viewHolder द्वारा दिए गए के बजाय इस पर कॉल करें।

0

अच्छा, मैंने इसे थोड़ा अलग तरीके से संभाला, दूसरों की मदद कर सकता है।

 Collections.swap(mItemList, fromPosition, toPosition); 
     // Need to do below, because NotifyItemMove only handle one sided move 
     Item fromItem = mItemList.get(fromPosition); 
     Item toItem = mItemList.get(toPosition); 
     notifyItemChanged(fromPosition, toItem); 
     notifyItemChanged(toPosition, fromItem); 

मुझे एक ग्रिड पर वस्तुओं को पुन: व्यवस्थित करना था, और स्थिति को फ़ाइल में सहेजना पड़ा। @ ग्रेमे सही था, लेकिन मैं स्वैपिंग पर हार नहीं देना चाहता था। तो बस @ saganaut की तरह मैं सूचित करने के लिए चिपक गया ItemChanged। लेकिन केवल सूचित करें ItemChanged ने कभी-कभी मेरे ग्रिड पर एक ही आइटम के साथ दोनों स्वैप किए गए आइटम छोड़े, इसलिए मैंने आइटम्स चेंज किए गए आइटम को बाध्य किया। यह एनीमेशन को मार नहीं रहा है, और उम्मीद के रूप में काम कर रहा है।

संबंधित मुद्दे