Неправильный элемент выбран в Listview onItemClick

Столкнулся с очень странной проблемой. У меня есть listview с checkbox для каждого элемента, когда я нажимаю на первый элемент listview, он выбирается, но наряду с этим элементом выбирается последний элемент списка! когда я прокручиваю список. Без прокрутки работает идеально.

Также, когда я выбираю последний элемент, первый элемент выбирается вместе с ним после прокрутки. Напоминаем, что все остальные элементы между первым и последним работают правильно. И самое смешное, что после выбора первого или последнего элемента, если я не прокручиваю listview в течение 2-3 секунд, он работает отлично. Так что я ожидаю, что это может быть проблема просмотра рендеринг или несколько. Может кто-нибудь указать мне, что, черт возьми, здесь происходит ..

Cursor cursor = queryDatabase();

    // The desired columns to be bound
      String[] columns = new String[] {               
        DataBaseHelper.ROW_PROFILE_NAME,
        DataBaseHelper.ROW_PROFILE_TYPE,
        DataBaseHelper.ROW_ID
      };

      // the XML defined views which the data will be bound to
      int[] to = new int[] { 
        R.id.profileName,
        R.id.profileStatus
      };

      // create the adapter using the cursor pointing to the desired data 
      //as well as the layout information
      mAdapter = new SimpleCursorAdapter(
        this, R.layout.profile_listview_delete_item, 
        cursor, 
        columns, 
        to,
        0);

      listView = (ListView) findViewById(R.id.profile_listview_delete_main);
      // Assign adapter to ListView
      listView.setAdapter(mAdapter);

      listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
            // TODO Auto-generated method stub

            CheckBox cb;                

            Cursor c = mAdapter.getCursor();
            String prodile_id = c.getString(c.getColumnIndex(DataBaseHelper.ROW_ID));

            cb = (CheckBox)arg1.findViewById(R.id.checkbox);
            cb.toggle();

            if(cb.isChecked())
            {                   
                profileStack.add(prodile_id);                   
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter++;              
            }
            else if(!cb.isChecked())
            {
                profileStack.remove(prodile_id);                    
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter--;                  
            }               
            countSelectedItem.setText(String.valueOf(counter)+" items selected");

            mAdapter.notifyDataSetChanged();                                
        }
    });

person ridoy    schedule 29.09.2014    source источник
comment
Не могли бы вы опубликовать свой класс адаптера? Я думаю, что это проблема шаблона держателя представления?   -  person Rajesh    schedule 29.09.2014
comment
@Rajesh, я использую SimpleCursorAdapter, как вы можете видеть в коде выше.   -  person ridoy    schedule 29.09.2014
comment
Ваш способ кода неверен. Вы должны использовать пользовательский адаптер с классом viewholder. Из этого адаптера при изменении значения вашего флажка вы должны изменить значение поля из вашего адаптера в отношении этого флажка. После нажатия списка просмотрите позицию и получите значения от вашего адаптера.   -  person Gunaseelan    schedule 29.09.2014
comment
Проверьте: заголовок stackoverflow.com/questions/25844210/.   -  person Haresh Chhelana    schedule 29.09.2014
comment
возможный дубликат Просмотр списка Android дублирует элемент при прокрутке   -  person Shruti    schedule 29.09.2014
comment
@Shruti, это не тот дубликат, о котором вы упомянули. Вы проверяете мой код? я использовал notifyDataSetChanged() там.   -  person ridoy    schedule 29.09.2014


Ответы (3)


Для этого вы должны использовать пользовательский Adapter (и класс модели - это optional. Здесь TemaRescatado - это класс модели во фрагменте). В getView(...) вы должны использовать CompoundButton.OnCheckedChangeListener, попробуйте использовать шаблон ViewHolder

фрагмент кода

viewHolder.checkbox = (CheckBox) view.findViewById(R.id.checkBox1);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

      @Override
      public void onCheckedChanged(CompoundButton buttonView,
         boolean isChecked) {
         TemaRescatado element = (TemaRescatado) viewHolder.checkbox
                  .getTag();
         element.setSelected(buttonView.isChecked());

         }
      });
person Kaushik    schedule 29.09.2014
comment
Нельзя ли исправить проблему с текущим кодом? Потому что я сказал, что все остальные элементы работают хорошо. - person ridoy; 29.09.2014
comment
Я не уверен, но лучше использовать собственный адаптер, потому что он оптимизирует ваш код, а реализация ViewHolder шаблона ListView's прокрутки будет гладкой - person Kaushik; 29.09.2014
comment
можно попробовать с mAdapter.notifyDataSetInvalidated() после notifyDataSetChanged(). - person Kaushik; 29.09.2014
comment
как предложил @kaushik ... используйте viewholder, иначе вы получите нежелательный результат - person kgandroid; 29.09.2014
comment
@kaushik, notifyDataSetInvalidated() тоже не работает, я знаю, что ViewHolder может решить эту проблему, но изменить код конечного приложения будет долгой задачей! - person ridoy; 29.09.2014
comment
@ridoy: просто следуйте этому руководству, и вам понадобится всего полчаса, чтобы реализовать его. - person Kaushik; 29.09.2014

Вы должны получить курсор из AdapterView, который передается в качестве аргумента методу onItemClick.

Измените код.

Cursor c = mAdapter.getCursor();

to

Cursor c = (Cursor) arg0.getItemAtPosition(position);
person Mohan Krishna    schedule 29.09.2014
comment
Нет, это не меняет ситуацию. - person ridoy; 29.09.2014
comment
Обновлен мой ответ, проверьте это и дайте мне знать, что он работает или нет. - person Mohan Krishna; 29.09.2014
comment
нет, это не работает. Все то же самое, проверьте 1-й элемент, а затем прокрутите, видно, что последний элемент также выбран! Но проверьте 1-й пункт, подождите 2 секунды, прокрутите и увидите, что он работает хорошо! странный! - person ridoy; 29.09.2014

Эта проблема возникает из-за утилизации ListView. Он повторно использует первые видимые View, как только они не видны, чтобы показать следующие данные адаптера. Поэтому, когда вы устанавливаете флажок и устанавливаете флажок в отношении данных в позиции List. он останется таким же, каким вы его оставили. Итак, мое решение этой проблемы:

в getView() вашего адаптера

поместите простой оператор if-else, чтобы проверить, должен ли флажок быть установлен или нет:

// note that this is a pseudo code
if(ID exist in profileStack){
//set checkBox
}
else{
//set checkBox
}
person Ercan    schedule 29.09.2014