RecyclerView में विशिष्ट आइटम को अद्यतन / ताज़ा कैसे करें


112

मैं विशिष्ट आइटम को ताज़ा करने की कोशिश कर रहा हूं RecyclerView

कहानी: जब भी उपयोगकर्ता आइटम पर क्लिक करता है, यह दिखाता है AlertDialog। उपयोगकर्ता ठीक बटन पर क्लिक करके कुछ पाठ लिख सकता है। मैं इस आइटम को इस आइटम में दिखाना चाहता हूं और अदृश्य दिखाना चाहता हूं ImageView- एक्सएमएल और एडॉप्टर में घोषित ViewHolder-

मैंने इस फ़ंक्शन का उपयोग AlertDialogआइटम को अपडेट करने के लिए पॉजिटिव बटन में किया है:

private void updateListItem(int position) {
  View view = layoutManager.findViewByPosition(position);
  ImageView medicineSelected = (ImageView) view.findViewById(R.id.medicine_selected);
  medicineSelected.setVisibility(View.VISIBLE);
  TextView orderQuantity = (TextView) view.findViewById(R.id.order_quantity);
  orderQuantity.setVisibility(View.VISIBLE);
  orderQuantity.setText(quantity + " packet added!");

  medicinesArrayAdapter.notifyItemChanged(position);
}

लेकिन यह कोड न केवल दिए गए स्थान पर आइटम दृश्य को बदलता है, बल्कि कुछ अन्य आइटम व्यू (एस) को भी बदलता है!

मुझे उस पर क्लिक करके विशिष्ट आइटम दृश्य को सही तरीके से कैसे बदलना चाहिए?

जवाबों:


98

आप notifyItemChanged(int position)RecyclerView.Adcape क्लास से विधि का उपयोग कर सकते हैं । प्रलेखन से:

किसी भी पंजीकृत पर्यवेक्षकों को सूचित करें कि स्थिति में आइटम बदल गया है। कॉल करने के लिए बराबर है InformItemChanged (स्थिति, शून्य); -

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

जैसा कि आपके पास पहले से ही स्थिति है, यह आपके लिए काम करना चाहिए।


9
मैंने पहले से ही इसका इस्तेमाल किया था, लेकिन अगर मैं स्थिति 0 को अपडेट करना चाहता हूं, तो यह 0, 9, 19 को अपडेट कर रहा है ...
Elgendy

क्षमा करें, आपकी टिप्पणी समझ में नहीं आई। यह किस स्थिति में अद्यतन कर रहा है? 0, 9 या 0 और 9 के बीच की सीमा?
एडसन मेनेगट्टी

नहीं, यह सीमा नहीं है, हर बार जब मैं आइटम को अपडेट कर रहा हूं, तो यह अवांछित वस्तुओं को भी ताज़ा कर रहा है
एलगेंडी

@ Learner जब आप स्थिति 0 पर ViewHolder अद्यतन करते हैं, तो यह अद्यतन रहता है। RecyclerView उस ViewHolder को रीसायकल करेगा और इसे स्थिति 9 के लिए उपयोग करेगा, इसलिए आप वहां उन परिवर्तनों को देख सकते हैं। मैं इस पाठ को onBindViewHolder () के बजाय सेट करने की सलाह देता हूं - इस तरह, जब भी कोई ViewHolder पुनर्नवीनीकरण किया जाता है, तो आप इसकी स्थिति की जांच कर सकते हैं और पाठ सेट कर सकते हैं या छवि को दृश्यमान कर सकते हैं या जो भी सही ढंग से दिखाई दे सकते हैं।
क्लिभच

@ कालीबच में अभी भी एक ही समस्या हैonBindViewHolder()
चोल्त्स्की

39

एकल आइटम अद्यतन करें

  1. डेटा आइटम को अपडेट करें
  2. के साथ परिवर्तन के अनुकूलक को सूचित करें notifyItemChanged(updateIndex)

उदाहरण

"भेड़" आइटम बदलें ताकि यह कहे कि "मुझे भेड़ पसंद है।"

एकल आइटम अद्यतन करें

String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);

अधिक उदाहरणों के साथ मेरा पूरा जवाब यहाँ है


अगर मैं अपडेट किए गए डेटा स्विच को शीर्ष
चोय

@Choy, डेटा अपडेट करने के बाद आप इसे इंडेक्स में स्थानांतरित कर सकते हैं। इस आइटम
Suragch

11

परिवर्तित पाठ को अपनी मॉडल डेटा सूची में जोड़ें

mdata.get(position).setSuborderStatusId("5");
mdata.get(position).setSuborderStatus("cancelled");
notifyItemChanged(position);

10

मुझे लगता है कि इससे निपटने के लिए मेरे पास एक आइडिया है। अद्यतन करना ठीक स्थिति पर हटाने और बदलने के समान है। इसलिए मैं सबसे पहले नीचे दिए गए कोड का उपयोग करके उस स्थिति से आइटम को हटाता हूं:

public void removeItem(int position){
    mData.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, mData.size());
}

और फिर मैं आइटम को उस विशेष स्थिति में जोड़ दूंगा जैसा कि नीचे दिखाया गया है:

public void addItem(int position, Landscape landscape){
    mData.add(position, landscape);
    notifyItemInserted(position);
    notifyItemRangeChanged(position, mData.size());
}

मैं अब इसे लागू करने की कोशिश कर रहा हूं। जब मैं आपके माध्यम से होऊंगा तो मैं आपको एक प्रतिक्रिया दूंगा!


2
आप एक अतिरिक्त कदम उठा रहे हैं। बस स्थिति पर तत्व को बदलें और आइटम को सूचित करें InformItemChanged (स्थिति);
toshkinl

@toshkinl आपको यह कैसे पता चलेगा कि डेटा JSONObject से कब आ रहा है? कोई स्थिति नहीं है
ओलाजाइड

7

मुझे इस समस्या को हल करने के लिए उस आइटम की स्थिति को पकड़ना पड़ा जिसे संशोधित करने की आवश्यकता थी और फिर एडेप्टर कॉल में

public void refreshBlockOverlay(int position) {
    notifyItemChanged(position);
}

, यह इस विशिष्ट स्थिति पर इस विशिष्ट आइटम के लिए onBindViewHolder (ViewHolder धारक, int स्थिति) को कॉल करेगा।


2

नीचे समाधान मेरे लिए काम किया:

RecyclerView आइटम पर, उपयोगकर्ता एक बटन पर क्लिक करेगा, लेकिन टेक्स्टव्यू की तरह एक और दृश्य सीधे एडाप्टर को सूचित किए बिना अपडेट होगा:

मैंने इसके लिए NotDataSetChanged () पद्धति का उपयोग किए बिना एक अच्छा समाधान पाया, यह विधि recyclerView के सभी डेटा को पुनः लोड करती है इसलिए यदि आपके पास आइटम के अंदर छवि या वीडियो है तो वे पुनः लोड करेंगे और उपयोगकर्ता का अनुभव अच्छा नहीं होगा:

यहाँ एक ImageView जैसे आइकन पर क्लिक करने का एक उदाहरण है और केवल +1 जोड़ने के बाद गिनती अपडेट की तरह दिखाने के लिए एक एकल TextView (समान आइटम के एक ही तरीके से अधिक दृश्य को अपडेट करना संभव है) को अपडेट करें:

// View holder class inside adapter class
public class MyViewHolder extends RecyclerView.ViewHolder{

    ImageView imageViewLike;

    public MyViewHolder(View itemView) {
         super(itemView);

        imageViewLike = itemView.findViewById(R.id.imageViewLike);
        imageViewLike.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = getAdapterPosition(); // Get clicked item position
                TextView tv = v.getRootView().findViewById(R.id.textViewLikeCount); // Find textView of recyclerView item
                resultList.get(pos).setLike(resultList.get(pos).getLike() + 1); // Need to change data list to show updated data again after scrolling
                tv.setText(String.valueOf(resultList.get(pos).getLike())); // Set data to TextView from updated list
            }
        });
    }

1

एक ऐसा तरीका जिसने मेरे लिए व्यक्तिगत रूप से काम किया है, वह पुनर्नवीनीकरण के एडेप्टर विधियों का उपयोग करके इसमें आइटम्स में परिवर्तन से निपटने के लिए है।

यह इस तरह से एक तरह से जाएगा, अपने कस्टम रिसाइक्लर के दृष्टिकोण में कुछ इस तरह से एक विधि बनाएँ:

public void modifyItem(final int position, final Model model) {
    mainModel.set(position, model);
    notifyItemChanged(position);
}

0

अपने एडेप्टर वर्ग में, ऑन-व्यू व्यूहोल्डर विधि में, नीचे दिए गए कोड के अनुसार ViewHolder को setIsRecyclable (गलत) पर सेट करें।

@Override
public void onBindViewHolder(RecyclerViewAdapter.ViewHolder p1, int p2)
{
    // TODO: Implement this method
    p1.setIsRecyclable(false);

    // Then your other codes
}

0

आपको बस सेव क्लिक पर अलर्ट डायलॉग बॉक्स में निम्नलिखित कोड जोड़ना होगा

          recyclerData.add(position, updateText.getText().toString());
          recyclerAdapter.notifyItemChanged(position);

0

समस्या RecyclerView.Adatperकिसी भी विधि को प्रदान नहीं करती है जो तत्व के सूचकांक को वापस करती है

public abstract static class Adapter<VH extends ViewHolder> {
  /**
   * returns index of the given element in adapter, return -1 if not exist
   */
  public int indexOf(Object elem);
}

मेरा वर्कअराउंड (तत्व, स्थिति) के लिए एक मानचित्र उदाहरण बनाना है

public class FriendAdapter extends RecyclerView.Adapter<MyViewHolder> {
  private Map<Friend, Integer> posMap ;
  private List<Friend> friends;

  public FriendAdapter(List<Friend> friends ) {
    this.friends = new ArrayList<>(friends);
    this.posMap = new HashMap<>();
    for(int i = 0; i < this.friends.size(); i++) {
      posMap.put(this.friends.get(i), i);
    }
  }

  public int indexOf(Friend friend) {
    Integer position = this.posMap.get(elem);
    return position == null ? -1 : position;
  }
  // skip other methods in class Adapter
}
  • तत्व प्रकार (यहाँ वर्ग Friend) को लागू करना चाहिए hashCode()और equals()क्योंकि यह हैशमैप में कुंजी है।

जब एक तत्व बदल गया,

  void someMethod() {
    Friend friend = ...;
    friend.setPhoneNumber('xxxxx');

    int position = friendAdapter.indexOf(friend);
    friendAdapter.notifyItemChanged(position);

  }

एक सहायक विधि को परिभाषित करना अच्छा है

public class FriendAdapter extends extends RecyclerView.Adapter<MyViewHolder> {

  public void friendUpdated(Friend friend) {
    int position = this.indexOf(friend);
    this.notifyItemChanged(position);
  }
}

मानचित्र उदाहरण ( Map<Friend, Integer> posMap) आवश्यक नहीं है। यदि मानचित्र का उपयोग नहीं किया जाता है, तो पूरी सूची में लूपिंग एक तत्व की स्थिति पा सकता है।


-1

यही मेरी आखिरी समस्या भी है। यहां मेरा समाधान मैं अपने RecyclerView के लिए डेटा मॉडल और एडाप्टर का उपयोग करता हूं

 /*Firstly, register your new data to your model*/
 DataModel detail = new DataModel(id, name, sat, image);

 /*after that, use set to replace old value with the new one*/
 int index = 4;
 mData.set(index, detail);

 /*finally, refresh your adapter*/
 if(adapter!=null)
    adapter.notifyItemChanged(index);

-1

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


-5

आपके RecyclerView एडेप्टर में, आपके पास ArrayList होना चाहिए और ArrayList में addItemsToList(items)सूची आइटम जोड़ने के लिए एक तरीका भी होना चाहिए । फिर आप adapter.addItemsToList(items)गतिशील रूप से कॉल करके सूची आइटम जोड़ सकते हैं । ArrayList में आपके सभी सूची आइटम जोड़े जाने के बाद आप adapter.notifyDataSetChanged()अपनी सूची प्रदर्शित करने के लिए कॉल कर सकते हैं ।

आप notifyDataSetChangedRecyclerView के लिए एडेप्टर में उपयोग कर सकते हैं


हाँ, मेरे पास डेटा के लिए ArrayList है, यह बिना किसी समस्या के काम करता है, इस सूची में विशिष्ट-उत्थापन-वस्तु को अपडेट करने में मेरी समस्या
Elgendy

आपके पास आइटम की स्थिति होनी चाहिए जो अपडेट कर रहे हैं, आपको बस नई वस्तु को संबंधित स्थिति जैसे mList.ad. स्थिति (स्थिति) .setName ("नया नाम") पर रखना होगा; उसके बाद mAdapter.notifyDataSetChanged () का उपयोग करें;
नूरुद्दीन लखानी

4
यह उत्तर किसी एक आइटम को अपडेट करने की इच्छा को अनदेखा करता है। जब पूरा डेटा सेट बदल जाता है तब ही CallDataSetChanged () किया जाना चाहिए।
मार्क मैक्लेलैंडैंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.