使用 sqlite 数据库在 RecyclerView 中滚动时,切换按钮会更改其状态
toggle button changed its state when scrolled in RecyclerView with mysqlite database
这是我的代码
@Override
public void onBindViewHolder(final RecyclerViewHolder holder, int position) {
final Songs songs = arrayList.get(position);
holder.favorite.setChecked(songs.getFavorite()); // this line makes me confusing.
holder.favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
int r = db.update_favorite(b,songs.getTitle(),songs.getArtist());
compoundButton.setChecked(b);
}
});
}
这里的问题是如果我包含这段代码
holder.favorite.setChecked(songs.getFavorite());
到onBindViewHolder,当我更改切换按钮的状态并向下滚动然后向上滚动时,切换按钮的状态会自行更改为原始状态。澄清一下,当切换按钮状态从 false 变为 true 并且用户向下和向上滚动时,切换按钮会自动变为原始状态,即 false。
如何让切换按钮保持状态的变化,即使用户向下滚动?请帮助我。
这是我的猜测:CompoundButton.OnCheckedChangeListener
在您意想不到的时间触发。
假设您有 100 首歌曲,每首歌曲开始时都不受欢迎。您激活与歌曲 #5 关联的 CompoundButton
,这会触发它的 OnCheckedChangeListener
并将歌曲 #5 标记为您数据库中的最爱。然后向下滚动,直到歌曲 #5 不再出现在屏幕上。
在某些时候,之前与歌曲 #5 关联的 ViewHolder
将被回收,然后 re-used 显示另一首歌曲。届时,将调用 onBindViewHolder()
。这将触发这条线:
holder.favorite.setChecked(songs.getFavorite());
请记住,此 ViewHolder
曾经与歌曲 #5 相关联,因此 CompoundButton
在该行运行之前被 选中 。由于新歌 不是 最喜欢的,此行将 更改 CompoundButton
以便取消选中。
这将触发 onCheckedChangeListener
. 但此时听众尚未重新分配,因此仍引用歌曲 #5。由于 CompoundButton
已从选中更改为未选中,听众会将歌曲 #5 标记为 不 您数据库中的收藏夹。
然后听众被重新分配,现在指的是新歌。但此时,伤害已经造成。
你可以通过简单地添加
来解决这个问题
holder.favorite.setOnCheckedChangeListener(null);
在onBindViewHolder()
开头。
Ben P. 很好地解释了问题的原因。只是想在解决方案中添加一些内容。
不要在开关上监听 check change 事件,而是监听 click 事件。在 switch 上,check 事件可以因许多其他原因而被触发。但是click只有在用户点击switch的时候才会触发。
希望我能够正确解释这些事情。
谢谢。
在适配器中添加以下方法后,它也为我解决了:
@Override
public int getItemViewType(int position) {
return position;
}
这是我的代码
@Override
public void onBindViewHolder(final RecyclerViewHolder holder, int position) {
final Songs songs = arrayList.get(position);
holder.favorite.setChecked(songs.getFavorite()); // this line makes me confusing.
holder.favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
int r = db.update_favorite(b,songs.getTitle(),songs.getArtist());
compoundButton.setChecked(b);
}
});
}
这里的问题是如果我包含这段代码
holder.favorite.setChecked(songs.getFavorite());
到onBindViewHolder,当我更改切换按钮的状态并向下滚动然后向上滚动时,切换按钮的状态会自行更改为原始状态。澄清一下,当切换按钮状态从 false 变为 true 并且用户向下和向上滚动时,切换按钮会自动变为原始状态,即 false。
如何让切换按钮保持状态的变化,即使用户向下滚动?请帮助我。
这是我的猜测:CompoundButton.OnCheckedChangeListener
在您意想不到的时间触发。
假设您有 100 首歌曲,每首歌曲开始时都不受欢迎。您激活与歌曲 #5 关联的 CompoundButton
,这会触发它的 OnCheckedChangeListener
并将歌曲 #5 标记为您数据库中的最爱。然后向下滚动,直到歌曲 #5 不再出现在屏幕上。
在某些时候,之前与歌曲 #5 关联的 ViewHolder
将被回收,然后 re-used 显示另一首歌曲。届时,将调用 onBindViewHolder()
。这将触发这条线:
holder.favorite.setChecked(songs.getFavorite());
请记住,此 ViewHolder
曾经与歌曲 #5 相关联,因此 CompoundButton
在该行运行之前被 选中 。由于新歌 不是 最喜欢的,此行将 更改 CompoundButton
以便取消选中。
这将触发 onCheckedChangeListener
. 但此时听众尚未重新分配,因此仍引用歌曲 #5。由于 CompoundButton
已从选中更改为未选中,听众会将歌曲 #5 标记为 不 您数据库中的收藏夹。
然后听众被重新分配,现在指的是新歌。但此时,伤害已经造成。
你可以通过简单地添加
来解决这个问题holder.favorite.setOnCheckedChangeListener(null);
在onBindViewHolder()
开头。
Ben P. 很好地解释了问题的原因。只是想在解决方案中添加一些内容。
不要在开关上监听 check change 事件,而是监听 click 事件。在 switch 上,check 事件可以因许多其他原因而被触发。但是click只有在用户点击switch的时候才会触发。
希望我能够正确解释这些事情。
谢谢。
在适配器中添加以下方法后,它也为我解决了:
@Override
public int getItemViewType(int position) {
return position;
}