This is a common error, I think. You need to set this code
holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener()
outside the if/else block. The reason is whether convertView is = null or not, the listener should be set. I realize your code may need bit of arrangement but I think you could do that better than me since my code style is different. Is this clear enough though?
Another possible error is holder.favorite.setTag(position)
. The reason is code Model element = (Model) holder.favorite.getTag()
in your listener. You're saving the int position
and typecasting it to the Model
class, could not work. Change the override getItem, first coding to do. Sample code in summary:
@Override
public Object getItem(int position) {
return data.get(position); // return the Model
}
...
holder.favorite.setTag( getItem(position) );
Note: Again holder.favorite.setTag should be set outside the if/else block. Only view.setTag(holder) could be set in the if block because it's a new view object.
Besides all this, I think your code design should work!
Suggested code changes...
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null; // different
if (convertView == null) {
...
holder.favorite.setTag(data.get(position)); // different
view.setTag(holder); // different
}
else {
view = convertView;
holder = (ViewHolder) view.getTag(); // different
}
...
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Model element = (Model) buttonView.getTag(); // different
Changes are:
- I use comments of different to emphasize code changes.
ViewHolder holder
is declared here in getView
(). Remove the holder declaration on top inside the class. I think this is better coding style since holder is closer to find where you're using it, make it local to getView.
- The placement of
holder.favorite.setTag
and view.setTag
is switched. I think this is a safer coding style. I think it is safer to set the holder first before using it as a parameter to object view. It may not matter, I admit.
view.getTag
is necessary when convertView is not = null. When you set the tag with view.getTag()).favorite.setTag
in the same block, you're actually changing the content of the holder with unexpected behavior.
- In code
(Model) buttonView.getTag()
, buttonView is used instead of holder.favorite. I hope this gets the correct Model object.