我的应用是一个简单的清单。如果我单击一个复选框并关闭该应用程序,则该复选框的状态将在重新启动时保存并重新加载。
现在,我想添加一个日历来选择日期。对于每个新的一天,应取消选中列表中复选框的默认状态。
如果复选框的状态更改,则应在该特定日期保存该复选框。因此,如果我关闭应用程序并再次选择同一天,则应重新加载复选框状态。
如何保存复选框状态,具体取决于日期和列表视图中单击的复选框?
我仍然可以使用sharedPreferences来做到这一点吗?还是我应该使用SQLite,因为使用一年会导致保存3650个复选框状态(假设我的清单包含大约10个项目)。
答案 0 :(得分:1)
这是逻辑答案。您需要自己实施。
使用SQLite并根据需要的列(根据复选框)创建带有日期字段的表。
现在选择日期后的日期,在数据库中查询所需的日期。并设置复选框(如果该日期存在数据)。
答案 1 :(得分:1)
这是您可以执行SQLite方面的一种方法。
数据库由一个包含11列的表组成。
数据库帮助器 DBHelper.java (SQLiteOpenHelper类的子类)具有强制性/覆盖
mDB = new DBHelper(this);
)。addNewDayEntry
的方法,该方法将添加没有标记为已设置复选框的行。setDayEntryForOneCheckBox
日期的复选框(1-10)。isDayEntryCheckboxSet
getCheckboxColumnNameFromNumber
代码是:-
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TB_DAYENTRIES = "day_entries";
public static final String DAYENTRIES_COL_DATE = "_date";
public static final String DAYENTRIES_COL_CB01 = "_cb01";
public static final String DAYENTRIES_COL_CB02 = "_cb02";
public static final String DAYENTRIES_COL_CB03 = "_cb03";
public static final String DAYENTRIES_COL_CB04 = "_cb04";
public static final String DAYENTRIES_COL_CB05 = "_cb05";
public static final String DAYENTRIES_COL_CB06 = "_cb06";
public static final String DAYENTRIES_COL_CB07 = "_cb07";
public static final String DAYENTRIES_COL_CB08 = "_cb08";
public static final String DAYENTRIES_COL_CB09 = "_cb09";
public static final String DAYENTRIES_COL_CB10 = "_cb10";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl_sql = "CREATE TABLE IF NOT EXISTS " + TB_DAYENTRIES + "(" +
DAYENTRIES_COL_DATE + " TEXT PRIMARY KEY NOT NULL," +
DAYENTRIES_COL_CB01 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB02 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB03 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB04 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB05 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB06 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB07 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB08 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB09 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB10 + " INTEGER DEFAULT 0" +
")";
db.execSQL(crt_tbl_sql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public long addNewDayEntry(String date) {
ContentValues cv = new ContentValues();
cv.put(DAYENTRIES_COL_DATE,date);
return mDB.insert(TB_DAYENTRIES,null,cv);
}
public int setDayEntryForOneCheckBox(String date, int checkbox) {
int rv = 0;
String whereclause = DAYENTRIES_COL_DATE + "=?";
String[] whereargs = new String[]{date};
ContentValues cv = new ContentValues();
switch (checkbox) {
case 1:
cv.put(DAYENTRIES_COL_CB01,1);
break;
case 2:
cv.put(DAYENTRIES_COL_CB02,1);
break;
case 3:
cv.put(DAYENTRIES_COL_CB03,1);
break;
case 4:
cv.put(DAYENTRIES_COL_CB04,1);
break;
case 5:
cv.put(DAYENTRIES_COL_CB05,1);
break;
case 6:
cv.put(DAYENTRIES_COL_CB06,1);
break;
case 7:
cv.put(DAYENTRIES_COL_CB07,1);
break;
case 8:
cv.put(DAYENTRIES_COL_CB08,1);
break;
case 9:
cv.put(DAYENTRIES_COL_CB09,1);
break;
case 10:
cv.put(DAYENTRIES_COL_CB10,1);
break;
}
if (cv.size() == 1) {
rv = mDB.update(TB_DAYENTRIES,cv,whereclause,whereargs);
}
return rv;
}
public boolean isDayEntryCheckboxSet(String date, int checkbox) {
boolean rv = false;
String whereclause = DAYENTRIES_COL_DATE + "=?";
String[] whereargs = new String[]{date};
if (checkbox < 1 || checkbox > 10) {
return rv;
}
Cursor csr = mDB.query(TB_DAYENTRIES,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getInt(csr.getColumnIndex(getCheckboxColumnNameFromNumber(checkbox))) == 1;
}
csr.close();
return rv;
}
private String getCheckboxColumnNameFromNumber(int checkbox) {
switch (checkbox) {
case 1:
return DAYENTRIES_COL_CB01;
case 2:
return DAYENTRIES_COL_CB02;
case 3:
return DAYENTRIES_COL_CB03;
case 4:
return DAYENTRIES_COL_CB04;
case 5:
return DAYENTRIES_COL_CB05;
case 6:
return DAYENTRIES_COL_CB06;
case 7:
return DAYENTRIES_COL_CB07;
case 8:
return DAYENTRIES_COL_CB08;
case 9:
return DAYENTRIES_COL_CB09;
case 10:
return DAYENTRIES_COL_CB10;
}
return "";
}
}
MainActivity.java 是一项活动:-
getWritableDatbase()
方法)。代码是:-
public class MainActivity extends AppCompatActivity {
DBHelper mDB;
String[] checkdates = new String[]{"2018-09-10","2018-09-11","2018-09-09"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDB = new DBHelper(this);
mDB.addNewDayEntry("2018-09-10");
mDB.setDayEntryForOneCheckBox("2018-09-10",1);
mDB.setDayEntryForOneCheckBox("2018-09-10",3);
mDB.setDayEntryForOneCheckBox("2018-09-10",8);
mDB.setDayEntryForOneCheckBox("2010-09-09",7); //<<<<<<<<<< wont set as DAY ENTRY NOT ADDED
StringBuilder sb = new StringBuilder("");
for (String s: checkdates) {
sb.append("\nChecking Date ").append(s);
for(int i=1; i <= 10; i++) {
sb.append("\n\tCHECKBOX ").append(String.valueOf(i)).append(" IS ").append(String.valueOf(mDB.isDayEntryCheckboxSet(s,i)));
}
}
Log.d("CHECKBOX STATES",sb.toString());
}
}
产生的输出是:-
10-01 10:17:46.753 1467-1467/? D/CHECKBOX STATES: Checking Date 2018-09-10
CHECKBOX 1 IS true
CHECKBOX 2 IS false
CHECKBOX 3 IS true
CHECKBOX 4 IS false
CHECKBOX 5 IS false
CHECKBOX 6 IS false
CHECKBOX 7 IS false
CHECKBOX 8 IS true
CHECKBOX 9 IS false
CHECKBOX 10 IS false
Checking Date 2018-09-11
CHECKBOX 1 IS false
CHECKBOX 2 IS false
CHECKBOX 3 IS false
CHECKBOX 4 IS false
CHECKBOX 5 IS false
CHECKBOX 6 IS false
CHECKBOX 7 IS false
CHECKBOX 8 IS false
CHECKBOX 9 IS false
CHECKBOX 10 IS false
Checking Date 2018-09-09
CHECKBOX 1 IS false
CHECKBOX 2 IS false
CHECKBOX 3 IS false
CHECKBOX 4 IS false
CHECKBOX 5 IS false
CHECKBOX 6 IS false
CHECKBOX 7 IS false
CHECKBOX 8 IS false
CHECKBOX 9 IS false
CHECKBOX 10 IS false
mDB.setDayEntryForOneCheckBox("2010-09-09",7); //<<<<<<<<<< wont set as DAY
行表明,如果尝试更新未添加条目的日期,则setDatEntryForOneCheckbox方法不会失败。答案 2 :(得分:1)
从MikeT的答案继续,这是如何执行ListView并在选中复选框时更改基础数据。
您需要将ListView添加到主布局中,例如:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ListView
android:id="@+id/cblist"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
Listview的每个项目的布局,例如:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/entrydate"
android:layout_width="100dp"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb01"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb02"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb03"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb04"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb05"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb06"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb07"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb08"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb09"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<CheckBox
android:id="@+id/cb10"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
要使日期和复选框都可以由侦听器识别,请添加一个新类,例如
public class CBTag {
private String mEntrydate;
private int mCheckBoxNumber;
public CBTag(String entrydate, int checkboxnumber) {
this.mEntrydate = entrydate;
this.mCheckBoxNumber = checkboxnumber;
}
public int getCheckBoxNumber() {
return mCheckBoxNumber;
}
public void setCheckBoxNumber(int mCheckBoxNumber) {
this.mCheckBoxNumber = mCheckBoxNumber;
}
public String getEntrydate() {
return mEntrydate;
}
public void setEntrydate(String mEntrydate) {
this.mEntrydate = mEntrydate;
}
}
将需要一个自定义适配器,它将对列表中的每个项目使用以上布局,还将使用CBTag对象设置复选框的标签
public class CBListAdapter extends CursorAdapter {
private Context mContext;
private DBHelper mDB;
public CBListAdapter(Context context, Cursor cursor) {
super(context,cursor,0);
mContext = context;
mDB = new DBHelper(mContext);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position,convertView,parent);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return LayoutInflater.from(mContext).inflate(R.layout.cblist_item,viewGroup,false);
}
@Override
public void bindView(View view, Context context, Cursor csr) {
TextView entrydate = view.findViewById(R.id.entrydate);
String entry_date = csr.getString(csr.getColumnIndex(DBHelper.DAYENTRIES_COL_DATE));
entrydate.setText(entry_date);
CheckBox[] cblist = new CheckBox[]{
view.findViewById(R.id.cb01),
view.findViewById(R.id.cb02),
view.findViewById(R.id.cb03),
view.findViewById(R.id.cb04),
view.findViewById(R.id.cb05),
view.findViewById(R.id.cb06),
view.findViewById(R.id.cb07),
view.findViewById(R.id.cb08),
view.findViewById(R.id.cb09),
view.findViewById(R.id.cb10)
};
// For Each CheckBox set the tag as a CBTag object (Holds String for date and int for CheckBox #)
// Also add an onClick Listener that will update the applicable row/column and
// refresh the ListView
int cbidx = 0;
for (CheckBox c: cblist) {
c.setChecked(csr.getInt(cbidx + 1) == 1);
c.setTag(new CBTag(entry_date,cbidx + 1));
c.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CBTag cbtag = (CBTag) view.getTag();
mDB.setDayEntryForOneCheckBox(
cbtag.getEntrydate(),
cbtag.getCheckBoxNumber(),
((CheckBox)view).isChecked()
);
((MainActivity) mContext).refreshDateEntryList();
}
});
cbidx++;
}
}
}
对DatabaseHelper进行了一些更改,就像现在这样
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TB_DAYENTRIES = "day_entries";
public static final String DAYENTRIES_COL_DATE = "_date";
public static final String DAYENTRIES_COL_CB01 = "_cb01";
public static final String DAYENTRIES_COL_CB02 = "_cb02";
public static final String DAYENTRIES_COL_CB03 = "_cb03";
public static final String DAYENTRIES_COL_CB04 = "_cb04";
public static final String DAYENTRIES_COL_CB05 = "_cb05";
public static final String DAYENTRIES_COL_CB06 = "_cb06";
public static final String DAYENTRIES_COL_CB07 = "_cb07";
public static final String DAYENTRIES_COL_CB08 = "_cb08";
public static final String DAYENTRIES_COL_CB09 = "_cb09";
public static final String DAYENTRIES_COL_CB10 = "_cb10";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
String crt_tbl_sql = "CREATE TABLE IF NOT EXISTS " + TB_DAYENTRIES + "(" +
DAYENTRIES_COL_DATE + " TEXT PRIMARY KEY NOT NULL," +
DAYENTRIES_COL_CB01 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB02 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB03 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB04 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB05 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB06 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB07 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB08 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB09 + " INTEGER DEFAULT 0," +
DAYENTRIES_COL_CB10 + " INTEGER DEFAULT 0" +
")";
db.execSQL(crt_tbl_sql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public long addNewDayEntry(String date) {
ContentValues cv = new ContentValues();
cv.put(DAYENTRIES_COL_DATE,date);
return mDB.insert(TB_DAYENTRIES,null,cv);
}
public Cursor getDateEntryListAsCursor() {
String[] columns = new String[]{"*,rowid AS _id"};
return mDB.query(TB_DAYENTRIES,columns,null,null,null,null,null);
}
public int setDayEntryForOneCheckBox(String date, int checkbox, boolean status) {
int rv = 0;
String whereclause = DAYENTRIES_COL_DATE + "=?";
String[] whereargs = new String[]{date};
ContentValues cv = new ContentValues();
int value = 0;
if (status) {
value = 1;
}
switch (checkbox) {
case 1:
cv.put(DAYENTRIES_COL_CB01,value);
break;
case 2:
cv.put(DAYENTRIES_COL_CB02,value);
break;
case 3:
cv.put(DAYENTRIES_COL_CB03,value);
break;
case 4:
cv.put(DAYENTRIES_COL_CB04,value);
break;
case 5:
cv.put(DAYENTRIES_COL_CB05,value);
break;
case 6:
cv.put(DAYENTRIES_COL_CB06,value);
break;
case 7:
cv.put(DAYENTRIES_COL_CB07,value);
break;
case 8:
cv.put(DAYENTRIES_COL_CB08,value);
break;
case 9:
cv.put(DAYENTRIES_COL_CB09,value);
break;
case 10:
cv.put(DAYENTRIES_COL_CB10,value);
break;
}
if (cv.size() == 1) {
rv = mDB.update(TB_DAYENTRIES,cv,whereclause,whereargs);
}
return rv;
}
public boolean isDayEntryCheckboxSet(String date, int checkbox) {
boolean rv = false;
String whereclause = DAYENTRIES_COL_DATE + "=?";
String[] whereargs = new String[]{date};
if (checkbox < 1 || checkbox > 10) {
return false;
}
Cursor csr = mDB.query(TB_DAYENTRIES,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getInt(csr.getColumnIndex(getCheckboxColumnNameFromNumber(checkbox))) == 1;
}
csr.close();
return rv;
}
private String getCheckboxColumnNameFromNumber(int checkbox) {
switch (checkbox) {
case 1:
return DAYENTRIES_COL_CB01;
case 2:
return DAYENTRIES_COL_CB02;
case 3:
return DAYENTRIES_COL_CB03;
case 4:
return DAYENTRIES_COL_CB04;
case 5:
return DAYENTRIES_COL_CB05;
case 6:
return DAYENTRIES_COL_CB06;
case 7:
return DAYENTRIES_COL_CB07;
case 8:
return DAYENTRIES_COL_CB08;
case 9:
return DAYENTRIES_COL_CB09;
case 10:
return DAYENTRIES_COL_CB10;
}
return "";
}
}
上次主要活动已更改,现在就像
public class MainActivity extends AppCompatActivity {
DBHelper mDB;
ListView mLV;
CBListAdapter mCBLA;
Cursor mCsr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDB = new DBHelper(this);
loadInitialData();
mCsr = mDB.getDateEntryListAsCursor();
mLV = this.findViewById(R.id.cblist);
mCBLA = new CBListAdapter(this,mCsr);
mLV.setAdapter(mCBLA);
}
protected void onResume() {
super.onResume();
refreshDateEntryList();
}
public void refreshDateEntryList() {
mCsr = mDB.getDateEntryListAsCursor();
mCBLA.swapCursor(mCsr);
}
private void loadInitialData() {
long rowcount = DatabaseUtils.queryNumEntries(mDB.getWritableDatabase(),DBHelper.TB_DAYENTRIES);
if (rowcount > 0) return;
String[] dates_to_add = new String[]{"2018-09-09","2018-09-10","2018-09-11"};
for (String s: dates_to_add) {
mDB.addNewDayEntry(s);
}
mDB.setDayEntryForOneCheckBox("2018-09-10",3,true);
mDB.setDayEntryForOneCheckBox("2018-09-09",9,true);
}
}
看起来像这样
选中复选框会同时更改复选框以及数据库中的数据。