我已经用Room,ViewModel,LiveData,Recylerview实现了一个MVVM模式的android java应用程序。
带有1件或2件物品的Recyclerview很好,
但是当recyclerview项目增加时,例如> 10项,当我启用或禁用该复选框时,recyclerview中的其他项也会受到影响。
例如:
如果我更改项目[5]处的复选框(项目ID为21,复选框启用),它还会触发OnCheckedChangeListener以用于其他项目,例如项目[1](项目ID为15,复选框启用)和项目[8](商品ID为18,启用复选框)。
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);
,它修复了这个问题,但不推荐,我需要找到另一种机制来避免这种情况。
码:
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());
}
});
我想你需要通过holder.getAdapterPosition()
获得这个位置。那应该是正确的。
为什么? Because:
请注意,与ListView不同,如果项目的位置在数据集中发生更改,则RecyclerView不会再次调用此方法,除非项目本身无效或无法确定新位置。 ...如果您稍后需要某个项目的位置(例如在点击侦听器中),请使用具有更新的适配器位置的getAdapterPosition()。
另外:在onClickListener
中设置onBindViewHolder
不是最佳实践,因为每次调用onBindViewHolder
时都会设置监听器。将它设置在onCreateViewHolder中,因为onCreate仅在必须创建新的ViewHolder时调用,因此频率较低。
诀窍是设置复选框不可点击并自己手动检查。为此,您必须在数据列表中保持其状态,并根据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);
}
});
您必须设置else语句,因为视图是Recycled并使用“旧”视图。
或者你可以做这样的事情:
@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);
});
}
}