如何在 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
列中搜索值,然后设置同一列的值,并且由于此特定列是 true
或 false
,因此很容易出现大量重复值,并且此更新函数只会更新第一个结果。
编辑:
您需要搜索您的主键列,然后设置您想要的值。
像这样:
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
块中的代码。
所以我有 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
列中搜索值,然后设置同一列的值,并且由于此特定列是 true
或 false
,因此很容易出现大量重复值,并且此更新函数只会更新第一个结果。
编辑:
您需要搜索您的主键列,然后设置您想要的值。 像这样:
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
块中的代码。