如何在 sqlite 中保存 android 复选框状态?

how to save the android checkbox state in sqlite?

所以我有 recyclerview 和复选框 我可以检索 recylerview 的项目,但复选框不会保持选中状态。我在 sqlite 中为复选框值设置了 string,并为复选框状态使用了 true 和 false。

这是插入方法

public void insertProduct(String is_checked, ...)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(IS_CHECKED, is_checked);
        db.insert(DB_TABLE,  null, cv);        
    }

和更新方法

public void updateProduct(String is_checked)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(IS_CHECKED, is_checked);
        db.update(DB_TABLE, cv, IS_CHECKED+"=?", new String[]{is_checked});
    }

recyclerview

适配器的 onbindviewholder 内部
holder.productName.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b) {
                db.updateProduct("true");
                db.close();
            } else {
                db.updateProduct("false");
                db.close();
            }
        });

在主活动中,当我添加到列表时,我将值设置为 false,就像这样 db.insertProduct(product_name, list_name, "false");

这将加载所有列表

private void load_products()
    {   
        Cursor cursor = db.getAllProducts();

        if (cursor.getCount() > 0)
        {
            while (cursor.moveToNext())
            {
                product_id.add(cursor.getString(0));
                list_name.add(cursor.getString(1));
                product_name.add(cursor.getString(2));
                checkbox.add(cursor.getString(3));
            }
        }
    }

编辑

这是 SQliteOpenHelper

public class DbProducts extends SQLiteOpenHelper {

    private final static String DB_NAME = "products.db";
    private final static String PRODUCT_COLUMN = "product_name";
    private final static String LIST_COLUMN = "list_name";
    private final static String DB_TABLE = "products";
    private final static String ID_COLUMN = "product_id";
    private final static int VERSION = 1;
    private static final String IS_CHECKED = "is_checked";
    private final Context context;

    public DbProducts(Context context)
    {

        super(context, DB_NAME, null, VERSION);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
        String createStatement = "CREATE TABLE " + DB_TABLE +
                " ( " + ID_COLUMN +" INTEGER PRIMARY KEY AUTOINCREMENT,"
                + LIST_COLUMN + " TEXT, "
                +PRODUCT_COLUMN+ " TEXT, "
                +IS_CHECKED+ " TEXT)";
        db.execSQL(createStatement);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1)
    {db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);}

    public Cursor getAllProducts(String list_name)
    {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = null;
        if (db != null)
        {
            String productsQuery = " SELECT * FROM " +DB_TABLE+ " WHERE "+LIST_COLUMN+ "=?";
                cursor = db.rawQuery(productsQuery, new String[]{list_name});
        }
        return cursor;
    }

    public void insertProduct(String product_name, String list_name, String is_checked)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(PRODUCT_COLUMN, product_name);
        cv.put(LIST_COLUMN, list_name);
        cv.put(IS_CHECKED, is_checked);
        long insert = db.insert(DB_TABLE,  null, cv);
        if (insert == -1)
        {
            Toast.makeText(context, "Failed to add "+product_name+
                    "\nplease try again", Toast.LENGTH_SHORT).show();
        }
        else
        {db.close();}
    }


    public void updateProduct(String product_name, String list_name, String is_checked)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(PRODUCT_COLUMN, product_name);
        cv.put(LIST_COLUMN, list_name);
        cv.put(IS_CHECKED, is_checked);

        int update = db.update(DB_TABLE, cv, "?", new String[]{product_name});

        if (update == -1)
        {
            Toast.makeText(context, "not updated", Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(context, "updated \n"+"prod "+product_name
                    +" list "+list_name
                    +" status "+is_checked
                    +" num of rows "+update
                    , Toast.LENGTH_LONG).show();
        }
    }
}

和使用的适配器

public class MyproductsAdapter extends RecyclerView.Adapter<MyproductsAdapter.MyproductsViewHolder>
{
    private final ArrayList<String> product_id;
    private final ArrayList<String> product_name;
    private final Context context;

    public MyproductsAdapter(Context context, ArrayList<String> list_name,
                             ArrayList<String> product_id, ArrayList<String> product_name,
                             ArrayList<String>checkbox)
    {

        this.product_id = product_id;
        this.product_name = product_name;
        this.context = context;
    }

    @NonNull
    @Override
    public MyproductsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
    {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.product_wrapper_item, parent, false);
        return new MyproductsAdapter.MyproductsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyproductsViewHolder holder, int position)
    {
        holder.btun.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view)
            {
                holder.productName.setChecked(true);
                DbProducts db = new DbProducts(context);
                db.updateProduct("name updated","list updated", "true");
            }
        });
        holder.productName.setText(String.valueOf(product_name.get(position)));
        holder.id.setText(String.valueOf(product_id.get(position)));
        holder.productName.setOnCheckedChangeListener((compoundButton, b) -> {
            if (b) {
                DbProducts db = new DbProducts(context);
                db.updateProduct("name updated","list updated", "true");
                //db.close();
                int checked = Color.parseColor("#E4E4E4"); // "SELECTED" IN COLORS.VALUES
                holder.singleProductItem.setBackgroundColor(checked);
            } else
            {
                DbProducts db = new DbProducts(context);
                db.updateProduct("name updated","list updated", "false");
                //db.close();
                int unchecked = Color.parseColor("#FFFFFFFF"); // "SELECTED" IN COLORS.VALUES
                holder.singleProductItem.setBackgroundColor(unchecked);
            }
        });
    }

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

    public static class MyproductsViewHolder extends RecyclerView.ViewHolder
    {
        private final CheckBox productName;
        private final TextView id;
        private final ConstraintLayout singleProductItem;
        private final Button btun;

        public MyproductsViewHolder(@NonNull View itemView)
        {
            super(itemView);
            productName = itemView.findViewById(R.id.checkable_product);
            id = itemView.findViewById(R.id.product_id);
            singleProductItem = itemView.findViewById(R.id.single_product_item);
            btun = itemView.findViewById(R.id.btn);
        }
    }
}

确保 IS_CHECKED 的值与存储检查状态值的列的名称完全相同。

而且你的 updateProduct 方法对我来说没有意义。您正在 IS_CHECKED 列中搜索值,然后设置同一列的值,并且由于此特定列是 truefalse,因此很容易出现大量重复值,并且此更新函数只会更新第一个结果。

编辑:

您需要搜索您的主键列,然后设置您想要的值。 像这样:

public void updateProduct(int productID, String product_name, String list_name, String is_checked)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(PRODUCT_COLUMN, product_name);
        cv.put(LIST_COLUMN, list_name);
        cv.put(IS_CHECKED, is_checked);
        db.update(DB_TABLE, cv, ID_COLUMN + "=?", new String[]{productID});
    }

现在应该可以了。显然,您还应该更改 setOnCheckedChangeListener 块中的代码。