You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将CheckBox选中状态保存到Room数据库并解决重启应用状态丢失问题

核心问题

共3处错误导致状态未持久化:

  • 列表中CheckBox的选中变更事件没有关联数据库更新逻辑
  • MainActivity中监听的CheckBox是单独inflate出来的无效View,和RecyclerView实际渲染的条目完全无关
  • 执行更新操作时新建的Todo对象没有携带原有主键ID,Room的@Update逻辑依赖主键匹配数据,找不到对应行自然不会执行更新

修复方案

1. 修改TodoAdapter,新增状态变更回调

给Adapter添加回调接口,在CheckBox选中事件触发时把修改后的Todo实体回传给调用层:

public class TodoAdapter extends RecyclerView.Adapter<TodoAdapter.ViewHolder>{
    private List<Todo> todos = new ArrayList<>();
    // 新增回调接口
    public interface OnCheckedChangeListener {
        void onCheckedChanged(Todo todo);
    }
    private OnCheckedChangeListener listener;

    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        this.listener = listener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(TodoItemBinding.inflate(LayoutInflater.from(parent.getContext()),parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Todo currentTodo = todos.get(holder.getAbsoluteAdapterPosition());
        holder.binding.tvTitle.setText(currentTodo.getTitle());
        holder.binding.checkBox.setChecked(currentTodo.getChecked());
        holder.binding.checkBox.setOnCheckedChangeListener(null);
        holder.binding.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 更新当前Todo的选中状态
                currentTodo.setChecked(isChecked);
                // 触发回调
                if (listener != null) {
                    listener.onCheckedChanged(currentTodo);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return todos == null ? 0 : todos.size();
    }

    public void setTodos(List<Todo> todos){
        this.todos = todos;
        notifyDataSetChanged();
    }

    class ViewHolder extends RecyclerView.ViewHolder{
        private TodoItemBinding binding;

        public ViewHolder(TodoItemBinding bind){
            super(bind.getRoot());
            this.binding = bind;
        }
    }
}

2. 修改MainActivity,清理无效代码实现回调

删除所有和todoItemBinding相关的代码(包括初始化、CheckBox点击监听逻辑),给Adapter设置回调处理数据库更新:

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private TodoViewModel todoViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        RecyclerView recyclerView = binding.recyclerView;
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        TodoAdapter todoAdapter = new TodoAdapter();
        recyclerView.setAdapter(todoAdapter);

        todoViewModel = new ViewModelProvider(this).get(TodoViewModel.class);
        todoViewModel.getTodo().observe(this, new Observer<List<Todo>>() {
            @Override
            public void onChanged(List<Todo> todos) {
               todoAdapter.setTodos(todos);
            }
        });

        // 设置CheckBox状态变更回调
        todoAdapter.setOnCheckedChangeListener(new TodoAdapter.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(Todo todo) {
                // 直接用传入的已有ID的Todo对象执行更新
                todoViewModel.update(todo);
            }
        });

        binding.btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addTodo();
            }
        });
    }

    private void addTodo() {
        String title = binding.editText.getText().toString().trim();
        if (title.isEmpty()) {
            return;
        }
        Todo todo = new Todo(title,false);
        todoViewModel.insert(todo);
        binding.editText.setText("");
        closeKeyboard();
    }

    private void closeKeyboard(){
        View view = this.getCurrentFocus();
        if (view != null) {
            InputMethodManager manager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
}

内容的提问来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:15:04