У розумінні загального принципу дії і призначення адаптера вам, можливо, допоможе ця відповідь.
Далі, чому стану чекбоксів змінюються при прокручуванні.
При створенні поточного Айтем адаптер не завжди створює його розмітку заново, для прискорення роботи він використовує вже створену раніше розмітку для Айтем, який в даний час не бачимо на екрані, так як вона ідентична для всіх Айтем списку. При цьому, якщо примусово не заповнювати поточний Айтем даними в методі getView () адаптера, то він бере те, що залишилося в минулий раз в тому вигляді, в якому воно було при останньому (пере) використанні. Від цього і з'являється ефект, коли віджети з станами довільно "скачуть". З усього цього зокрема слід, що ніякі "блокування" чекбоксів не вирішать цю проблему, тому що ви просто бачите на екрані ті Айтем, які перебували вище (нижче) за списком і тепер зникли за кордоном екрану.
Рішення просте. При формуванні кожного Айтем примусово встановлювати стану, відповідні саме тій позиції, яка в даний момент відображається на екрані. Для цього ці стани потрібно десь окремо зберігати. Оскільки ви працюєте з класом-моделлю і виділили спеціальне поле для зберігання стану чекбокса, то їм і слід користуватися. При зміні стану чекбокса (кліці на ньому або всім Айтем) новий стан необхідно записувати в модель. Для цього необхідно контролювати натискання через будь-якої слухач кліків і всі маніпуляції проводити в ньому.
У вашому ж коді якраз і відсутня збереження зміни станів при кліці. Для вирішення вашої проблеми, оскільки окремий слухач на чекбокс вам не потрібен і зміна стану здійснюється при натисканні на весь Айтем, в адаптері слід реалізувати метод-сетер. який змінюватиме модель цього адаптера, зберігаючи змінилося стан. Викликати цей метод треба буде з активують, при обробці слухача кліків на списку OnItemClickListener ().
Так само варто передбачити повернення змінених станів з адаптера (метод-геттер), коли всі необхідні позначки будуть зроблені, оскільки при виході з активують зі списком, адаптер і відповідно модель, передана в нього, будуть втрачені і ваші позначки пропадуть дарма.
Орієнтовна реалізація може виглядати так:
Так само кілька зауважень:
Якщо ви працюєте з БД, то вам краще всього використовувати класи, призначені для роботи з БД, наприклад Cursor і успадковуватися від SimpleCursorAdapter (). який повертає ID записів з БД або використовувати якусь з ORM.
Зокрема, зараз у вас така ситуація, що ви пишете в БД по позиції. але ID в БД не дорівнює значенню позиції в адаптері, при внесенні \ видаленні даних з БД позиція і ID будуть відрізняться, оскільки ID завжди присвоюється наступним за рахунком. Тобто, видаливши третю запис в БД (з, скажімо, п'яти) ви отримаєте наступну послідовність ID в базі: 0,1,3,4,5, в той час як позиції в списку будуть: 0,1,2,3, 4. Ви отримаєте помилку і запишіть дані не туди.
Так само рекомендується зробити клас-врапперов для роботи з БД, який буде реалізовувати методи записи, читання і тп операції CRUD, а не слати "сирі" запити, як ви робите зараз.