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

时间:2016-07-03 15:44:37

标签: android checkbox position android-recyclerview android-adapter

我有一个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();
    }

}

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

谢谢..

1 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。

问题是,在RecyclerView中,ViewHolder是Recycled。因此,在remove the OnCheckedChangeListener之前,Items将引用旧的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来存储已检查列表项的数据。 你在类对象中存储它的方式也很好

    编辑 - 添加代码以供参考

        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中实现了一个简单的逻辑来删除冗余调用。既然你提到他们是网络电话,这是必要的。