Сначала я подумал, что ответ 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());
}
}
});
}