OnCheckedChangeListener срабатывает при скролле

Рейтинг: 0Ответов: 1Опубликовано: 31.01.2015

Здравствуйте, уважаемые! У меня такой вопрос. У меня есть листвью, в котором есть некий чекбокс. И вот такой код:

public View getView(final int position, View convertView, ViewGroup parent) {

    CheckBox check = (CheckBox) view.findViewById(R.id.myCheckBox);
    if(check.getTag() == null) {
        check.setTag(position);
        check.setOnCheckedChangeListener(myCheckChangList);
    }
   check.setChecked(holders.get(position).isChecked);              
}

private OnCheckedChangeListener myCheckChangList = new OnCheckedChangeListener() {
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
          holders.get((Integer) buttonView.getTag()).isChecked = isChecked;
      }
};

Все вроде бы замечательно. Но проблема в том, что обработчик срабатывает не только при нажатии на чекбок, но почему-то еще и когда я прокручиваю листвью. Скажем, я нажимаю на чекбокс, чтобы сделать его отмеченным. Срабатывает листенер. Вроде все ок. Затем я прокручиваю листвью вниз, после чего прокручиваю обратно вверх и вижу, что отмеченный чекбокс снова без галки. Что за фигня, думаю я и пытаюсь все это отлаживать. Ставлю брейкпойнт внутри листенера и делаю то же самое. При нажатии на чекбокс брейкпойнт срабатывает - это логично. Однако когда я начинаю прокручивать листвью, то он внезапно тоже срабатывает. Получается, что при скроллинге листвью андроид зачем-то вызывает метод setChecked для чекбокса. Но зачем? И почему вообще так происходит? Заранее спасибо!

Ответы

▲ 1

Ничего удивительного. Когда вы прокручиваете ListView, для каждого элемента вызывается getView(), в котором у вас есть вот эта строка:

check.setChecked(holders.get(position).isChecked);

При выполнении этой строки как раз и вызовется onCheckedChanged.
Чтобы это исправить, придется немного поизвращаться. Например, изменить ваш getView() так:

public View getView(final int position, View convertView, ViewGroup parent) {

    CheckBox check = (CheckBox) view.findViewById(R.id.myCheckBox);
    if(check.getTag() == null) {
        check.setTag(position);

    }
    check.setOnCheckedChangeListener(null);

    check.setChecked(holders.get(position).isChecked);  
    check.setOnCheckedChangeListener(myCheckChangList);            
}

Советую вам, прежде чем начинать разотать с ListView, почитать какие-нибудь уроки по нему, понять, как работают Адаптеры и зачем нужны ViewHolder, а еще как происходит Recycling элементов списка. Такие вопросы сразу отпадут.