When working with a ListView it is very important to always keep in mind that the views are a presentation, and the adapter is a data model.
This means that all your state should be in the adapter (data model), and not in the views.
From what I can say about your code, you have a view showing the status of the check, and this state is in the view not in the adapter. That is, when a user clicks on this item in the list, the view used to display its item has its internal validation state, changed to switch what is shown to the user.
But since the view is not a data model, this state in which you play here is transient and is not actually associated with clicking on an adapter element.
The most obvious problem caused by this problem is related to the processing of the species. When you scroll through a ListView , when items scroll to the end and new ones appear below, views used to display old items are reused to display new ones. This is much more efficient than inflating a new hierarchy of item positions each time a new item is displayed.
Since you have your state in the view, when this recirculation occurs, the state in the view becomes randomly associated with some new element. This can happen in many cases, not just scrolling.
The solution is to put your validation state in the adapter and implement Adapter.getView() to set the verified state of the view based on the state you currently have in the adapter. Thus, whenever the view is processed (and getView() is called to bind a new row of data to it), you will update its checked state to correctly follow the new displayed data.
source share