在 Recylerview 中实现复选框。 MVVM Room ViewModel LiveData Recylerview 复选框
Implementing checkbox in a Recylerview. MVVM Room ViewModel LiveData Recylerview Checkbox
我已经使用 Room、ViewModel、LiveData、Recylerview 实现了 MVVM 模式 android java 应用程序。
- recyclerview 有一个项目列表,每个项目都有一个复选框。
- 当启用或禁用 recyclerview 项目的复选框时,
模型通过 ViewModel 在房间数据库中更新。
- 监听每个recyclerview的复选框启用或禁用事件
项,我已经实现了一个 OnCheckedChangeListener。
recyclerview 有 1 或 2 个项目没问题,
但是当 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);
,它解决了这个问题,但不推荐,我需要找到另一种机制来避免这种情况。
我认为你需要通过 holder.getAdapterPosition()
获得职位。那么它应该是正确的。
为什么? Because:
Note that unlike ListView, RecyclerView will not call this method
again if the position of the item changes in the data set unless the
item itself is invalidated or the new position cannot be determined.
... If you need the position of an item later on (e.g. in a click
listener), use getAdapterPosition() which will have the updated
adapter position.
此外:在 onBindViewHolder
中设置 onClickListener
不是最佳实践,因为每次调用 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);
}
});
- 将标签设置到您的复选框并从标签中获取项目。
- 不要使用 setOnCheckedChangeListener,而是使用 setOnClickListener。
代码:
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());
}
});
您必须设置 else 语句,因为该视图已回收并使用 "old" 视图。
或者你可以做这样的事情:
@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);
});
}
}
我已经使用 Room、ViewModel、LiveData、Recylerview 实现了 MVVM 模式 android java 应用程序。
- recyclerview 有一个项目列表,每个项目都有一个复选框。
- 当启用或禁用 recyclerview 项目的复选框时, 模型通过 ViewModel 在房间数据库中更新。
- 监听每个recyclerview的复选框启用或禁用事件 项,我已经实现了一个 OnCheckedChangeListener。
recyclerview 有 1 或 2 个项目没问题,
但是当 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);
,它解决了这个问题,但不推荐,我需要找到另一种机制来避免这种情况。
我认为你需要通过 holder.getAdapterPosition()
获得职位。那么它应该是正确的。
为什么? Because:
Note that unlike ListView, RecyclerView will not call this method again if the position of the item changes in the data set unless the item itself is invalidated or the new position cannot be determined. ... If you need the position of an item later on (e.g. in a click listener), use getAdapterPosition() which will have the updated adapter position.
此外:在 onBindViewHolder
中设置 onClickListener
不是最佳实践,因为每次调用 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);
}
});
- 将标签设置到您的复选框并从标签中获取项目。
- 不要使用 setOnCheckedChangeListener,而是使用 setOnClickListener。
代码:
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());
}
});
您必须设置 else 语句,因为该视图已回收并使用 "old" 视图。
或者你可以做这样的事情:
@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);
});
}
}