पहले तो मुझे लगा कि मूनसो का जवाब (स्वीकृत उत्तर) मेरे लिए काम नहीं करेगा क्योंकि मैं अपना इनिशियलाइज़ नहीं कर सकताsetOnCheckedChangeListener()
व्यूहॉल्डर कंस्ट्रक्टर में क्योंकि मुझे इसे हर बार बाँधने की ज़रूरत है इसलिए इसे एक अपडेटेड पोजिशन वेरिएबल मिलता है। लेकिन मुझे यह महसूस करने में काफी समय लगा कि वह क्या कह रहा है।
यहाँ "सर्कुलर मेथड कॉल" का एक उदाहरण है जिसके बारे में वह बात कर रहे हैं:
public void onBindViewHolder(final ViewHolder holder, final int position) {
SwitchCompat mySwitch = (SwitchCompat) view.findViewById(R.id.switch);
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
data.delete(position);
notifyItemRemoved(position);
//This will call onBindViewHolder, but we can't do that when we are already in onBindViewHolder!
notifyItemRangeChanged(position, data.size());
}
}
});
//Set the switch to how it previously was.
mySwitch.setChecked(savedSwitchState); //If the saved state was "true", then this will trigger the infinite loop.
}
इसके साथ एकमात्र समस्या यह है कि जब हमें स्विच को चालू या बंद करने की आवश्यकता होती है (उदाहरण के लिए, पूर्व में सहेजे गए राज्य से), तो यह उस श्रोता को कॉल कर रहा है, nofityItemRangeChanged
जो कॉल कर सकता है जो onBindViewHolder
फिर से कॉल करता है । आप कॉल नहीं कर सकते हैं onBindViewHolder
जब आप में पहले से ही कर रहे हैं onBindViewHolder
], क्योंकि आप नहीं कर सकते हैं notifyItemRangeChanged
अगर आप पहले से सूचित किया जाएगा कि आइटम रेंज बदल गया है के बीच में हैं। लेकिन मुझे केवल इसे चालू या बंद दिखाने के लिए यूआई को अपडेट करने की आवश्यकता थी, वास्तव में कुछ भी ट्रिगर नहीं करना चाहता था।
यहाँ वह समाधान है जो मैंने JoniDS के उत्तर से सीखा है जो अनंत लूप को रोक देगा। जब तक हम चेकर को सेट करने से पहले श्रोता को "अशक्त" करते हैं, तब तक यह अनन्त लूप से बचते हुए, श्रोता को ट्रिगर किए बिना UI को अपडेट कर देगा। फिर हम श्रोता को बाद में सेट कर सकते हैं।
जोनीडीएस कोड:
holder.checkbox.setOnCheckedChangeListener(null);
holder.checkbox.setChecked(condition);
holder.checkbox.setOnCheckedChangeListener(checkedListener);
मेरे उदाहरण के लिए पूर्ण समाधान:
public void onBindViewHolder(final ViewHolder holder, final int position) {
SwitchCompat mySwitch = (SwitchCompat) view.findViewById(R.id.switch);
//Set it to null to erase an existing listener from a recycled view.
mySwitch.setOnCheckedChangeListener(null);
//Set the switch to how it previously was without triggering the listener.
mySwitch.setChecked(savedSwitchState); //If the saved state was "true", then this will trigger the infinite loop.
//Set the listener now.
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
data.delete(position);
notifyItemRemoved(position);
//This will call onBindViewHolder, but we can't do that when we are already in onBindViewHolder!
notifyItemRangeChanged(position, data.size());
}
}
});
}