Флажок становится "липким" в RecyclerView

У меня есть диалог, который вводит пользовательский ввод через список с флажками, чей макет - RecyclerView. Но когда я выбираю CheckBox в списке, еще один элемент CheckBox далее в списке также проверяется, но которого я не делал. Эти образы помогут проиллюстрировать мою точку зрения.

Здесь я выбрал только Календарь и Камера:

введите описание изображения здесь

но далее в списке Google и Карты также выбираются, которые я не выбрал.

введите описание изображения здесь

Мой код для bindActivity:

public void bindActivity(ResolveInfo resolveInfo)
        {
            mResolveInfo = resolveInfo;
            PackageManager pm = getActivity().getPackageManager();
            String appName = mResolveInfo.loadLabel(pm).toString();
            mAppImageView.setImageDrawable(resolveInfo.loadIcon(pm));
            mAppTextView.setText(appName);
        }

Если я добавлю mAppCheckBox.setChecked(false) в bindActivity, тогда, когда я перейду в списке вниз, а RecyclerView переработает список, а затем я поднимусь, мой предыдущий выбор не будет выбран.

Мне бы понравились любые предложения о том, как избавиться от флажка "липкий".

Ответ 1

Вы видите это поведение, потому что ViewHolder повторно используются. После прокрутки вниз ViewHolder верхних элементов (которые теперь не видны) будут повторно использоваться для новых элементов, которые будут отображаться. Этот ViewHolder имел CheckBox, который был проверен ранее, и никто прямо не сказал, что он должен быть снят.

Вы должны позаботиться о правильном восстановлении состояния. Вы можете сохранить отмеченные позиции позиций в массиве, а затем в onBindViewHolder() соответствующим образом установить выбранное состояние CheckBox:

public class MyAdapter extends RecyclerView.Adapter<Item> {

  final boolean[] checkedArr;

  public MyAdapter(List<Item> list) {
    checkedArr = new boolean[list.size()];
    // Filling all the items as unchecked by default
    Arrays.fill(checkedArr, false);
  }

  @Override public void onBindViewHolder(Item holder, int position) {
    // You have removed the listener in `onViewRecycled`
    // Thus, this `setChecked()` won't cause any listener to be fired
    holder.checkbox.setChecked(checkedArr[holder.getAdapterPosition()]);
    holder.checkbox.setOnCheckedChangeListener(
        (buttonView, isChecked) -> {
          // Retaining checked state in the array
          checkedArr[holder.getAdapterPosition()] = isChecked;
        });
  }

  @Override public void onViewRecycled(Item holder) {
    super.onViewRecycled(holder);
    // When view is being recycled remove the listener
    holder.checkbox.setOnCheckedChangeListener(null);
  }
  ...
}

Или вы можете воздержаться от "переосмысления колеса" и использовать MultiViewAdapter, который отправляется с checkboxes: одиночная, одиночная или ни одна, несколько режимов.

Ответ 2

a) Не похоже, что вы устанавливаете флажок установленного флажка, когда вы привязываете представление. Отслеживайте элементы, которые были выбраны, и установите установленное состояние, когда вы выполняете привязку вида.

b) Я не совсем уверен, что вы имеете в виду, но из того, что я собираю, диалоговое dokumenation может быть то, что вы ищете для связи с родителем.