如何在 recyclerview 中保存复选框位置?

How to save check box position in recyclerview?

我有一个 checkListItems 列表。列表项有一个复选框。我想保存项目的状态。状态保存为 0 或 1。

我根据状态 0 或 1 显示选中或未选中的复选框。

它有时显示正确,但当我上下滚动时,更多项目被选中或取消选中,我没有手动完成。

适配器:

    public class CheckListItemAdapter extends RecyclerView.Adapter<CheckListItemAdapter.MyViewHolder>{

    private List<CheckListItem> checkListItems;
    Context context;
    private String status;

    private final OnItemClickListener listener;

    public interface OnItemClickListener {
        void onItemClick(CheckListItem item);
    }
    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title, budget;
        public RelativeLayout parent;
        private CheckBox checkBox;


        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.title);
            budget =(TextView) view.findViewById(R.id.budget);
            checkBox = (CheckBox) view.findViewById(R.id.checkBox);

        }


        public void bind(final CheckListItem item, final OnItemClickListener listener) {

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    listener.onItemClick(item);
                }
            });
        }
    }


    public CheckListItemAdapter(List<CheckListItem> checkListItems,Context context,OnItemClickListener listener) {
        this.checkListItems = checkListItems;
        this.context = context;
        this.listener = listener;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.checklist_item, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {

        final CheckListItem item = checkListItems.get(position);
        holder.title.setText(item.getTitle());
        holder.budget.setText(item.getBudget());

        status = item.getStatus();

        if(status.equals("1"))
        {
            holder.checkBox.setChecked(true);
        }
        if(status.equals("0")) {

            holder.checkBox.setChecked(false);
        }

        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                if (isChecked) {

                    status = "1";

                    HashMap<String, String> params = new HashMap<String, String>();


                    params.put("checklistItemId", item.getCheckListItemId());
                    params.put("budget",item.getBudget());
                    params.put("text", item.getTitle());
                    params.put("time_due", item.getDateTime());
                    params.put("reminder",item.getReminder());
                    params.put("status", status);


                    new UpdateCheckListItemsAsyncTask(context).execute(params);


                } else

                {
                    status = "0";

                    HashMap<String, String> params = new HashMap<String, String>();

                    params.put("checklistItemId", item.getCheckListItemId());
                    params.put("budget",item.getBudget());
                    params.put("text", item.getTitle());
                    params.put("time_due", item.getDateTime());
                    params.put("reminder",item.getReminder());
                    params.put("status", status);

                    new UpdateCheckListItemsAsyncTask(context).execute(params);

                }

            }

        });


        holder.bind(checkListItems.get(position), listener);

    }

    @Override
    public int getItemCount() {
        return checkListItems.size();
    }

}

这里出了什么问题?如何保存复选框的位置?

谢谢..

我遇到过类似的问题。

事实是,在 RecyclerView 中,ViewHolder 被回收。因此,在 remove the OnCheckedChangeListener 之前,项目将引用旧的 OnCheckedChangeListener。

    if(status.equals("1"))
    {
        holder.checkBox.setChecked(true);
    }
    if(status.equals("0")) {

        holder.checkBox.setChecked(false);
    }

这些行实际上触发了旧的 onCheckedChangedListener。

你可以试试这个。

  1. 添加行 holder.checkBox.setOnCheckedChangeListener(null); 作为 onBindViewHolder
  2. 的第一行
  3. 您可以实现接口调用并将 onCheckedChanged 逻辑转移到使用 getLayoutPosition()
  4. 的接口调用

关于你的第二个问题,

您可以使用HashSet来存储勾选列表项的数据。 您将其存储在 class 对象中的方式也很好

编辑-添加代码供参考

    public class CheckListItemAdapter extends RecyclerView.Adapter<CheckListItemAdapter.MyViewHolder> {
    ...
            ..

    public CheckListItemAdapter(List<CheckListItem> checkListItems, Context context, OnItemClickListener listener) {
        this.checkListItems = checkListItems;
        this.context = context;
        this.listener = listener;
    }
     @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {

      ....
        ....

            if(item.getStatus().equals("1"))
        {
            holder.checkBox.setChecked(true);
        }
        else {

            holder.checkBox.setChecked(false);
        }



    public MyViewHolder(View view) {
        super(view);
        title = (TextView) view.findViewById(R.id.title);
        budget = (TextView) view.findViewById(R.id.budget);
        checkBox = (CheckBox) view.findViewById(R.id.checkBox);
        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
             checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    int pos = getLayoutPosition();
                    CheckListItem currentItem=checkListItems.get(pos);
//to remove redundant calls to network while scrolling
                    if ( isChecked){
                        if (currentItem.getStatus().equals("1")) {
                            return;
                        } else {
                            currentItem.setStatus("1");
                        }
                    } else {
                        if (currentItem.getStatus().equals("0")) {
                            return;
                        } else {
                            currentItem.setStatus("0");
                        }
                    }
//network call, when check is changed
                    checkChangedLogic(checkListItems.get(pos), isChecked);
                }
            });

    }
}

注-

我在 onCheckedChanged 中实现了一个简单的逻辑来删除冗余调用。既然你提到它们是网络调用,那么这是必要的。