Android: сохранять состояние CheckBox в CheckList на разные дни - PullRequest
0 голосов
/ 01 октября 2018

Мое приложение представляет собой простой контрольный список.Если я установлю флажок и закрою приложение, состояние флажка будет сохранено и перезагружено при перезапуске.

Теперь я хочу добавить календарь, который можно использовать для выбора даты.Для каждого нового дня состояние флажков в списке по умолчанию должно быть снято.

Если состояние флажка изменяется, его следует сохранить на эту конкретную дату.Поэтому, если я закрою приложение и снова выберу тот же день, флажки должны быть перезагружены.

Как сохранить состояние флажка в зависимости от даты и в зависимости от того, какой флажок был выбран в просмотре списка?

И можно ли по-прежнему делать это с sharedPreferences?Или я должен использовать SQLite, потому что один год использования приведет к 3650 сохраненным состояниям флажков (при условии, что мой контрольный список содержит около 10 элементов).

Ответы [ 3 ]

0 голосов
/ 01 октября 2018

Вот способ, которым вы можете использовать сторону SQLite.

База данных состоит из одной таблицы с 11 столбцами.

  • Столбец для даты с именем / именем _date .
  • 10 столбцов для флажков с именем _cb01 , _cb02 , ......, _cb10

Помощник по базам данных DBHelper.java (подкласс класса SQLiteOpenHelper) имеет обязательный /overidden

  • onCreate (запускается один раз при создании базы данных) и
  • onUpgrade (запускается при увеличении номера версии базы данных, note ничего не делает ).
  • У него есть конструктор, который просто требует контекст (следовательно, mDB = new DBHelper(this); в действии, которое его использует).
  • У него есть метод для добавления строки addNewDayEntry, который добавляет строку без флажков, помеченных как установленные.
  • У него есть метод для обновления setDayEntryForOneCheckBox флажок (1-10) для даты.
  • У него есть метод проверки, установлен ли чекбокс или нет на указанную дату isDayEntryCheckboxSet
  • Используется частный методчтобы получить соответствующее имя столбца для флажка (1-10), а именно: 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 - это действие, которое: -

  • Создает экземпляр класса DBHelper (это создает базу данных с таблицей (поскольку она вызывает метод getWritableDatbase())).
  • Затем он добавляет одну строку, устанавливает некоторые индикаторы флажков, чтобы указать некоторые из устанавливаемых флажков (вы должны сделать это в соответствии с действиями пользовательского интерфейса).
  • Затем он проходит черезколичество дней и записывает состояние 10 флажков для этого дня в журнал.

Код: -

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
  • Примечания
  • все флажки для 2018-09-10 и 2018-09-09 являются ложными из-за отсутствия записей на эти даты (дни), имеющие
  • Строка mDB.setDayEntryForOneCheckBox("2010-09-09",7); //<<<<<<<<<< wont set as DAY демонстрирует, что метод setDatEntryForOneCheckbox не завершится ошибкой, еслисделана попытка обновить дату, за которую запись не была добавлена.
0 голосов
/ 02 октября 2018

Продолжая ответ 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>
  • Файл представляет собой activity_Main.xml

Макет для каждого элемента списка, например: -

<?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>
  • Файлcblist_item.xml

Для того, чтобы слушатель мог определить дату и флажок для нового класса, например

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.java

Потребуется настраиваемый адаптер, который будет использовать вышеуказанный макет для каждого элемента в списке, а также объекты 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);
    }
}
  • Это помещает 3 строки вТаблица также устанавливает некоторые строки для проверки.

Похоже, тhis

Установка флажка изменяет флажок, а также данные в базе данных.

enter image description here

0 голосов
/ 01 октября 2018

Вот логический ответ .. вам нужно реализовать его непосредственно.

  • Используйте SQLite и создайте таблицу с нужными столбцами (в соответствии с флажком)с полем даты также.

  • Теперь после даты выберите запрос к вашей базе данных на нужную дату .. и установите флажки, если данные существуют для даты.

...