假设我检查了一个项目checkbox
,该项目还会使用相应项目的ID更新ischecked
中的database
列。然后我向下滚动并返回到顶部,然后最顶部的项目checkbox
自动unchecked
,数据库也会更新。甚至假设我在顶部检查两个项目,当我向下滚动最底部的两个项目时,还会自动检查checkboxes
。如何在recyclerView
?
// costume adapter class
public class DataBeanAdapter extends RecyclerView.Adapter<DataBeanAdapter.ViewHolder> implements View.OnCreateContextMenuListener {
public List<dataBean> items;
public int itemLayout;
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo contextMenuInfo) {
menu.setHeaderTitle("Select The Action");
menu.add(0, v.getId(), 0, "Call");//groupId, itemId, order, title
menu.add(0, v.getId(), 0, "SMS");
}
public DataBeanAdapter(List<dataBean> items, int itemLayout) {
this.items = items;
this.itemLayout = itemLayout;
}
@Override
public DataBeanAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// On loading the activity recyclerview, setting properties to each list items
// fetch id with the given item postition
Cursor cc = myDB.getCursorByPosition(position);
String idd = cc.getString(cc.getColumnIndex("_id"));
String taskval = myDB.getTaskValue(idd);
dataBean item = items.get(position); // trash
holder.tasks.setText(taskval.trim());
String iscGet = myDB.getischecked(idd); // false by default
if (items.get(position).getChecked() == true) {
holder.isc.setChecked(true);
items.get(position).setChecked(true);
} else if (items.get(position).getChecked() == false) {
holder.isc.setChecked(false);
items.get(position).setChecked(false);
} else {
//leave
}
// set inflated checkbox to null
// holder.isc.setOnCheckedChangeListener(null);
// holder.isc.setChecked(myAdapter.items.contains(items.get(position)));
holder.isc.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Boolean ischecked = items.get(position).getChecked();
if (ischecked == false) {
Cursor cx = myDB.getCursorByPosition(position);
String idx = cx.getString(cx.getColumnIndex("_id"));
myDB.updateCheck(idx);
items.get(position).setChecked(true);
} else {
Cursor cx = myDB.getCursorByPosition(position);
String idx = cx.getString(cx.getColumnIndex("_id"));
myDB.updateunCheck(idx);
items.get(position).setChecked(false);
}
}
});
holder.tasks.setOnCreateContextMenuListener(MainActivity.this);
holder.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Cursor c = myDB.getCursorByPosition(position);
String id = c.getString(c.getColumnIndex("_id"));
Intent intent = new Intent(MainActivity.this, edit.class);
intent.putExtra("taskpos", Integer.toString(position));
intent.putExtra("taskid", id);
startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return items.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView tasks;
public CheckBox isc;
public ImageView more;
public ViewHolder(View itemView) {
super(itemView);
tasks = (TextView) itemView.findViewById(R.id.taskline);
isc = (CheckBox) itemView.findViewById(R.id.cbox);
more = (ImageView) itemView.findViewById(R.id.more);
// https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#isRecyclable()
// this.setIsRecyclable(false); /// prevents checkbox misbehaving
}
}
}
public List<dataBean> getAllData() {
List<dataBean> list = new ArrayList<>();
Cursor cursor = myDB.SelectData();
while (cursor.moveToNext()) {
int tasks = cursor.getColumnIndex("tasklist");
int ischecked = cursor.getColumnIndex("ischecked");
String tasksv = cursor.getString(tasks);
String ic = cursor.getString(ischecked);
dataBean bean = new dataBean(tasksv, Boolean.parseBoolean(ic));
list.add(bean);
}
return list;
}
答案 0 :(得分:0)
问题很糟糕,第一个答案也很糟糕。 RecyclerView回收组件,它是一个对象池,它通过重用组件并调用onBindViewHolder来实际设置要显示的数据来避免内存分配。
这意味着每当您的recyclerview的ViewHolder出现在屏幕上时,就会调用onBindViewHolder所有忙碌的工作(设置监听器和东西)。 OnBindViewHolder应该只读取数据并将其反映在持有者上,以便正确显示。
在您的情况下,错误在于您每次设置的OnCheckedChangeListener。回收ViewHolder时,会更改复选框以反映dataBean数组,并且该更改将保留在您的数据库中(当您的侦听器绑定到以前使用的ViewHolder的未知位置时,会插入不正确的数据)。然后设置监听器,必然会发生新的,不可预测的行为。
您应该检查一下RecyclerView上的一些教程,或者对Android SDK的文档/手册进行详细阅读,并尝试找出如何最好地布局代码。
希望这会有所帮助:)
答案 1 :(得分:0)
您必须使用共享首选项或在Sql数据库中保存复选框的状态。 注意:共享首选项是最佳解决方案。 使用共享首选项搜索如何保存复选框状态。
答案 2 :(得分:0)
我通过覆盖适配器类
中的两个方法解决了这个问题@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
还修改了每次视图被回收时从数据库中检索而不是从dataBean获取检查状态时直接检查和取消选中项目的条件。
if (iscGet.equals("true")) {
holder.isc.setChecked(true);
items.get(position).setChecked(true);
} else if (iscGet.equals("false")) {
holder.isc.setChecked(false);
items.get(position).setChecked(false);
} else {
//leave
}
答案 3 :(得分:0)
如果您在recylerview中的项目数少于上述答案,则可以使用它
recycler_filter.setItemViewCacheSize(100000);
答案 4 :(得分:0)
覆盖Adapter内部的方法
@Override public long getItemId(int position) { return ItemList.get(position).getId();}
每个项目的唯一 ID,可能来自数据库。 使用 OnClickListener 而不是 OnCheckChangedListener
holder.binding.alarmChk.setOnClickListener(view -> {
holder.binding.alarmChk.toggle();
if (holder.binding.alarmChk.isChecked()) {
//do something
Log.d("OnCheckedChange", "false " + getItemId(position));
holder.binding.alarmChk.setChecked(false);
} else {
//do something
Log.d("OnCheckedChange", "false " + getItemId(position));
holder.binding.alarmChk.setChecked(true);
}