2016-07-23 3 views
2

Я работаю там, где у меня есть флажок внутри RecyclerView элементов. Я знаю некоторые из его проблем. Но, только с 10 элементами и без прокрутки неправильного прослушивателя.Strange RecyclerView Checkbox onCheckChanged Behavior

У меня есть что-то вроде этого:

private class MyAdapter extends RecyclerView.Adapter<MyViewHodler> { 
    ArrayList<String> items; 
    ArrayList<String> checkedList = new ArrayList<>(); 
    ... 

    public void onBindViewHolder(final MyViewHolder holder, int position) { 
     String item = items.get(position); 
     String check = checkedList.get(item); 
     if(check != null) 
      holder.vChecked.setChecked(true); 
     else 
      holder.vChecked.setChecked(false); 

     .... 

     holder.vChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
       @Override 
       public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { 
        if (isChecked) { 
         checkedList.add(item); 
        } else { 
         checkedList.remove(item); 
        } 
       } 
    } 

} 

Теперь, как ни странно это checkedChange звонки сделаны на различных видах. У меня есть список из 10 предметов и подходит для recyclerview, без прокрутки. Я внешне изменяю данные (элементы и проверенный список), устанавливаю новые данные и звоня по телефону myAdapter.notifyDatasetChanged()

Этот звонок удаляет еще один элемент из состояния, в котором было проверено.

Например, у меня есть 10 предметов. Я снимите отметку с 1 пункта и сделаю некоторые другие вычисления, основанные на этом, и позвонив по номеру myAdapter.notifyDatasetChanged(). Он также отключает еще один элемент из других 9 элементов.

Итак, даже без прокрутки, почему прослушиватель onCheckedChange вызывается для неправильного представления?

ответ

1

Я выяснил, что проблема. Я думал, что для каждого вида для вызова данных вызывается onBindViewHolder. Но я был неправ.

notifyDatasetChanged() перерабатывает все держатели для просмотра на экране и из пула для повторного использования. Случайные зрители выбираются для привязки новых данных. Поэтому, когда я позвонил notifyDatasetChanged, зритель был использован в другом положении и, таким образом, изменил еще один элемент.

Итак, я удалил слушателя в нуль в методе recycler onViewRecycled. Например:

@Override 
    public void onViewRecycled(MyViewHolder holder) { 
     super.onViewRecycled(holder); 

     holder.vChecked.setOnCheckedChangeListener(null); 
    } 

Это решило проблему. Я знал об этом, но я думал, что зрители повторно используются для той же позиции, если нет прокрутки. Но onDatasetChanged перерабатывает все используемые в данный момент держатели и использует его снова из случайного пула.

1

Эта линия: String item = items.get(item);

Это беспокоит меня. Не должно быть String item = items.get(position);

Редактировать: Если вы изменили одну позицию набора данных, вызовите notifyItemChanged. Не уведомляйте весь набор данных, если он полностью не изменился. Может быть так.

Редактирование 2: Ну, тогда проблема не в том, что onCheckedChanged вызывается на неправильные представления. Он вызывается во всех представлениях, потому что вы всегда меняете состояние флажка на onBindViewHolder

+0

Ahhh .. Извините .. Это была опечатка .. Отредактированный вопрос .. – kirtan403

+0

Понял. Проверьте мое редактирование. –

+0

Основываясь на одном элементе, я меняю некоторые вычисления, которые отражаются во всех других элементах. Так что мне нужно позвонить notifyDatasetChanged – kirtan403