我已经用Room,ViewModel,LiveData和Recylerview实现了MVVM模式的android java应用程序。
带有1或2个项目的recyclerview很好,
但是,当recyclerview项增加(例如> 10个项)时,当我启用或禁用此复选框时,recyclerview中的其他项也会受到影响。
例如:
如果我更改了项目[5]的复选框(项目ID为21,启用了复选框), 它还会针对其他项目(例如item [1](项目ID为15,启用复选框)和item [8](项目ID为18,复选框启用)触发OnCheckedChangeListener。
Logcat:
2019-04-25 11:15:33.343 9890-9890/com.hardian.mvvm.sample D/RVAdapter: setOnCheckedChange--- ID :21 isRetryEnabled; false isChecked true
2019-04-25 11:15:33.405 9890-9890/com.hardian.mvvm.sample D/RVAdapter: setOnCheckedChange--- ID :15 isRetryEnabled; false isChecked true
2019-04-25 11:15:33.415 9890-9890/com.hardian.mvvm.sample D/RVAdapter: setOnCheckedChange--- ID :18 isRetryEnabled; false isChecked true
代码:在我的StatusRecyclerViewAdapter上
@Override
public void onBindViewHolder(StatusViewHolder holder, int position) {
StatusItem statusItem = mDataSet.get(position);
if (statusItem != null) {
cbStatus.setChecked(statusItem.isRetryEnabled());
cbStatus.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.d("RVAdapter", "setOnCheckedChange--- ID :" + statusItem.getId()+ " isRetryEnabled; "+statusItem.isRetryEnabled()+" isChecked "+isChecked);
//update the model via the activitiy's viewmodel through the onStatusCheckBoxChangeListener interface.
if (onStatusCheckBoxChangeListener != null)
onStatusCheckBoxChangeListener.onStatusCheckBoxChanged(statusItem,isChecked);
});
}
}
我需要一种解决方案来解决Recylerview回收问题。
注意:
我已经尝试过this.setIsRecyclable(false);
,它解决了该问题,但是不建议这样做,我需要找到另一种机制来避免这种情况。
答案 0 :(得分:2)
代码:
cbStatus.setTag(statusItem);
cbStatus.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
StatusItem item = (StatusItem) cb.getTag();
if (onStatusCheckBoxChangeListener != null)
onStatusCheckBoxChangeListener.onStatusCheckBoxChanged(item,cb.isChecked());
}
});
答案 1 :(得分:1)
我认为您需要通过holder.getAdapterPosition()
来获得职位。那么它应该是正确的。
为什么? Because:
请注意,与ListView不同,RecyclerView不会调用此方法 如果项目的位置在数据集中发生了变化,则再次 项目本身无效或无法确定新位置。 ...如果以后需要某个项目的位置(例如单击 侦听器),请使用getAdapterPosition()来更新 适配器位置。
也:在onClickListener
内设置onBindViewHolder
并不是最佳实践,因为每次调用onBindViewHolder
时都会设置监听器。在onCreateViewHolder中进行设置,因为onCreate仅在必须创建新的ViewHolder时才调用,因此不那么频繁。
答案 2 :(得分:0)
诀窍是将复选框设置为不可点击,并手动进行自我检查。为此,您必须将其状态保留在数据列表中,并根据CheckBox
中的值进行更新。
第一组CheckBox
不可点击。
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
下一步设置您的ClickListener
holder.cbStatus.setOnClickListener(v -> {
StatusItem statusItem = mDataSet.get(position);
if (cbStatus.isChecked()) {
cbStatus.setChecked(false);
statusItem.setChecked(false);
} else {
cbStatus.setChecked(true);
statusItem.setChecked(true);
}
});
答案 3 :(得分:0)
您必须设置else语句,因为该视图已回收并使用“旧”视图。
或者您可以像这样制作东西:
@Override
public void onBindViewHolder(StatusViewHolder holder, int position) {
StatusItem statusItem = mDataSet.get(position);
youCheckBox.setChecked(false);
if (statusItem != null) {
cbStatus.setChecked(statusItem.isRetryEnabled());
cbStatus.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.d("RVAdapter", "setOnCheckedChange--- ID :" + statusItem.getId()+ " isRetryEnabled; "+statusItem.isRetryEnabled()+" isChecked "+isChecked);
//update the model via the activitiy's viewmodel through the onStatusCheckBoxChangeListener interface.
if (onStatusCheckBoxChangeListener != null)
onStatusCheckBoxChangeListener.onStatusCheckBoxChanged(statusItem,isChecked);
});
}
}