Спочатку я подумав , що відповідь Moonsoo (прийнята відповідь) не буде працювати для мене, тому що я не можу ініціалізувати свою роботу setOnCheckedChangeListener()
в конструкторі ViewHolder, тому що мені потрібно прив'язувати її кожен раз, щоб отримати оновлену змінну позиції. Але мені знадобилося багато часу, щоб зрозуміти, що він говорить.
Ось приклад "кругового виклику методу", про який він говорить:
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, що запобіжить нескінченну петлю. Поки ми встановимо слухача на "null" перед тим, як встановити Checked, він оновить інтерфейс користувача, не запускаючи слухача, уникаючи нескінченного циклу. Тоді ми можемо встановити слухача після.
Код JoniDS:
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());
}
}
});
}