使用 SQLite 数据库保存 CheckBox 状态

Posted

技术标签:

【中文标题】使用 SQLite 数据库保存 CheckBox 状态【英文标题】:Saving CheckBox state with SQLite Database 【发布时间】:2018-08-17 13:30:10 【问题描述】:

我正在构建一个列表应用程序,它使用 SQLite 数据库来保存列表项。列表项由 UUID、名称和布尔值组成,以确定其是否已解决(数据库将其存储为 int)。我注意到的是,当用户关闭任务并添加新任务时,列表会重新加载,以便现在取消选中已检查的任务。此外,当应用程序重新启动时,列表会重新加载,因此所有已选中的任务都将变为未选中状态。

现在我一直在思考想法,到目前为止,我所做的是在我的 TaskAdapter 类中的 onBindViewHolder() 方法中,我调用 setOnCheckedChangedListener() 以便在用户检查任务时启动 toast。我觉得我应该在这里做一些事情来更新数据库中的特定任务,但我不知道如何。

附加说明:我正在使用一个单例类,其中包含所有数据库方法,例如添加任务、更新任务和从数据库中检索所有任务。

ListFragment.java

public class ListFragment extends Fragment implements AddTaskDialog.addTask

private static final String ADD_TASK_TAG = "ADD_TASK_DIALOG";
private RecyclerView mRecyclerView;
private TaskAdapter mAdapter;


@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_list, container, false);

    mRecyclerView = view.findViewById(R.id.recycler_view);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    mRecyclerView.setLayoutManager(layoutManager);
    updateUI();

    return view;


private void updateUI()
    List<Task> tasks = TaskLab.getTaskLab(getContext()).getTaskList();

    if(mAdapter == null) 
        mAdapter = new TaskAdapter(tasks);
        mRecyclerView.setAdapter(mAdapter);
    else
        mAdapter.setTaskList(tasks);
        mAdapter.notifyDataSetChanged();
    


@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.toolbar_layout,menu);


@Override
public boolean onOptionsItemSelected(MenuItem item) 

    switch (item.getItemId())
        case R.id.add_task_button:
            // Launch a dialog.
            AddTaskDialog dialog = new AddTaskDialog();
            FragmentManager manager = getFragmentManager();
            dialog.setTargetFragment(ListFragment.this,1);
            dialog.show(manager,ADD_TASK_TAG);
            return true;
        default:
            return super.onOptionsItemSelected(item);

    


// Part of the addTask interface created in AddTaskDialog
@Override
public void addTask(String taskName) 
    Task task = new Task();
    task.setName(taskName);
    TaskLab.getTaskLab(getContext()).addTask(task);
    updateUI();


TaskAdapter.java

public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskHolder> 

private List<Task> mTaskList;

public TaskAdapter(List<Task> tasks)
    mTaskList = tasks;

@Override
public TaskAdapter.TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_layout,parent,false);
    return new TaskHolder(view);


@Override
public void onBindViewHolder(TaskAdapter.TaskHolder holder, int position) 
    Task task = mTaskList.get(position);
    holder.bindData(task);

    holder.mTaskCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) 
            if(isChecked)
                Toast.makeText(compoundButton.getContext(),"Task Solved!",Toast.LENGTH_SHORT).show();
            
        
    );


@Override
public int getItemCount() 
    return mTaskList.size();


public void setTaskList(List<Task> tasks) 
    mTaskList = tasks;


public class TaskHolder extends RecyclerView.ViewHolder implements View.OnClickListener 

    private TextView mTaskName;
    private CheckBox mTaskCheckBox;

    public TaskHolder(View itemView) 
        super(itemView);
        mTaskName = itemView.findViewById(R.id.task_name);
        mTaskCheckBox = itemView.findViewById(R.id.task_checkbox);
    

    private void bindData(Task task) 
        mTaskName.setText(task.getName());
        mTaskCheckBox.setChecked(task.isSolved());
    

    @Override
    public void onClick(View view) 
    




TaskLab.java(单例类)

public class TaskLab 

private static TaskLab sTaskLab;
private Context mContext;

private SQLiteDatabase mDatabase;

private TaskLab(Context context) 
    mContext = context.getApplicationContext();
    mDatabase = new TaskBaseHelper(mContext).getWritableDatabase();


public static TaskLab getTaskLab(Context context)
    if(sTaskLab == null) 
        sTaskLab = new TaskLab(context);
    

    return sTaskLab;


// Add DataBase operation method here.

private ContentValues getContentValues(Task task) 
    ContentValues values = new ContentValues();
    values.put(TaskTable.Cols.UUID, task.getId().toString());
    values.put(TaskTable.Cols.NAME, task.getName());
    values.put(TaskTable.Cols.SOLVED, task.isSolved() ? 1 : 0);

    return values;


public void addTask(Task task) 
    ContentValues values = getContentValues(task);
    mDatabase.insert(TaskTable.TABLE_NAME,null,values);


// Don't really understand this method
public void updateTask(Task task) 
    String uuidString = task.getId().toString();
    ContentValues values = getContentValues(task);

    mDatabase.update(TaskTable.TABLE_NAME,values, TaskTable.Cols.UUID + " = ?",
            new String[] uuidString);


public TaskCursorWrapper queryTasks(String whereClause, String[] whereArgs) 
    Cursor cursor = mDatabase.query(TaskTable.TABLE_NAME,null,whereClause,whereArgs,null,null,null);
    return new TaskCursorWrapper(cursor);


public List<Task> getTaskList()

    List<Task> taskList = new ArrayList<>();
    TaskCursorWrapper cursor = queryTasks(null,null);

    try
        cursor.moveToFirst();
        while(!cursor.isAfterLast())
            Task task = cursor.getTask();
            taskList.add(task);
            cursor.moveToNext();
        
    finally 
        cursor.close();
    

    return taskList;

【问题讨论】:

您可以在模型类中使用任何布尔参数。并在此布尔参数中设置复选框状态。您可以将该参数值保存在数据库中。当您想从数据库中获取值时,只需检查布尔值并在复选框中设置该布尔值。 @HardikVaghasiya 我的模型类中确实有一个布尔参数。只是我无法从适配器类访问数据库,因为我的数据库存储在 TaskLab(单例类)中。如果我能以某种方式访问​​该数据库,那么我可以从 TaskLab 调用 updateTask() 方法,这样就可以完成工作。 【参考方案1】:

在adapter中,当你使用onclick时,当前项目会更新,但是在滚动时点击复选框的位置会不匹配。因为适配器只考虑您从您的代码中写入的位置。所以请使用任何 getter/setter 来避免这个问题。

【讨论】:

以上是关于使用 SQLite 数据库保存 CheckBox 状态的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQLite 和 PHP 将图像保存到数据库?

使用 iOS 应用更新保存 SQLite 数据

无法使用 sqlite3 在磁盘上保存数据库 - Python [重复]

SQLite 更改未保存

在 sqlite 数据库中保存坐标值

js对象在sqlite中保存和读取