如何根据数据库中的信息制作复选框?

How to make a checkbox from information found in DataBase?

我在数据库中有一个 table,我想创建一个 table。 现在,我会做很多 CheckBox 并根据 table 中的信息只显示其中的一些,这毫无意义。我听说了 但是怎么办 of 我在网上找了一个的例子,当我试图插入大信息时,只有一半的信息进来了,所以我被告知做 。 您有如何执行此操作的示例吗?

它的数据库处理程序:

package budgetreport.com.budgetreport;

public class DatabaseHandler extends SQLiteOpenHelper {

    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 4;

    // Database Name
    private static final String DATABASE_NAME = "Records_Item Purcashes";

    // Contacts table name
    private static final String TABLE_RECORDS = "Records";

    // Contacts Table Columns names
    private static final String KEY_ID = "ID";
    private static final String KEY_PRICE = "Price";
    private static final String KEY_ITEM = "Item";
    private static final String KEY_DETAILS = "Details";
    private static final String KEY_DATE = "Date";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_RECORDS + "("
                + KEY_ID + " INTEGER PRIMARY KEY,"
                + KEY_PRICE + " INTEGER," + KEY_ITEM + " TEXT,"
                + KEY_DETAILS + " TEXT, " + KEY_DATE + " TEXT" + ")";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECORDS);

        // Create tables again
        onCreate(db);
    }
    // Adding new contact
    public void addRecord(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(KEY_ID, record.getId()); // Contact Name
        values.put(KEY_PRICE, record.getPrice()); // Contact Name
        values.put(KEY_ITEM, record.getItem()); // Contact Name
        values.put(KEY_DETAILS, record.getDetails()); // Contact Name
        values.put(KEY_DATE, record.getDetails()); // Contact Phone Number

        // Inserting Row
        db.insert(TABLE_RECORDS, null, values);
        db.close(); // Closing database connection
    }
    // Getting single contact
    public Record getRecord(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_RECORDS, new String[] { KEY_ID, KEY_PRICE,
                        KEY_ITEM, KEY_DETAILS, KEY_DATE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Record record = new Record(Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)), cursor.getString(2), cursor.getString(3), cursor.getString(4));
        // return contact
        return record;
    }
    // Getting All Contacts
    public List<Record> getAllContacts() {
        List<Record> contactList = new ArrayList<Record>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_RECORDS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Record record = new Record();
                record.setId(Integer.parseInt(cursor.getString(0)));
                record.setPrice(Integer.parseInt(cursor.getString(1)));
                record.setItem(cursor.getString(2));
                record.setDetails(cursor.getString(3));
                record.setDate(cursor.getString(4));

                // Adding contact to list
                contactList.add(record);
            } while (cursor.moveToNext());
        }

        // return contact list
        return contactList;
    }
    // Getting contacts Count
    public int getRecordsCount() {
        String countQuery = "SELECT  * FROM " + TABLE_RECORDS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
       // cursor.close();

        // return count
        return cursor.getCount();
    }
    // Updating single contact
    public int updateContact(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, record.getId());
        values.put(KEY_PRICE, record.getPrice());
        values.put(KEY_DETAILS, record.getDetails());
        values.put(KEY_DATE, record.getDate());

        // updating row
        return db.update(TABLE_RECORDS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(record.getPrice()) });
    }
    // Deleting single contact
    public void deleteContact(Record record) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_RECORDS, KEY_ID + " = ?",new String[] 
       {String.valueOf(record.getPrice()) });
        db.close();
    }
}

这是一个基于您的代码的示例。

1) Activity 的布局(即 id 为 lv001 的 ListView)作为文件 activity_main.xml:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.budgetreport.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_margin="10dp"
        />

    <ListView
        android:id="@+id/lv001"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

2) 每行的布局(ListView 术语中的 Item)作为文件 listviewitem_record.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/record_price"
        android:layout_width="0dp"
        android:layout_weight="8"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_item"
        android:layout_width="0dp"
        android:layout_weight="10"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_details"
        android:layout_width="0dp"
        android:layout_weight="20"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <TextView
        android:id="@+id/record_date"
        android:layout_width="0dp"
        android:layout_weight="10"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
    <CheckBox
        android:id="@+id/record_checkbox"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>
</LinearLayout>
  • 注意!包含 CheckBox 以及所有列的 TextView。

3) 为了简化问题,我将其用作 DatabaseHandler.java :-

public class DatabaseHandler extends SQLiteOpenHelper {

    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 4;

    // Database Name
    public static final String DATABASE_NAME = "Records_Item Purcashes";

    // Contacts table name
    public static final String TABLE_RECORDS = "Records";

    // Contacts Table Columns names
    public static final String KEY_ID = "_id";
    public static final String KEY_PRICE = "Price";
    public static final String KEY_ITEM = "Item";
    public static final String KEY_DETAILS = "Details";
    public static final String KEY_DATE = "Date";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CONTACTS_TABLE = "CREATE TABLE " +
                TABLE_RECORDS +
                "(" +
                KEY_ID + " INTEGER PRIMARY KEY," +
                KEY_PRICE + " INTEGER," +
                KEY_ITEM + " TEXT," +
                KEY_DETAILS + " TEXT, " +
                KEY_DATE + " TEXT" +
                ")";
        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECORDS);

        // Create tables again
        onCreate(db);
    }

    public void insertRecord(int price, String item, String details, String date) {
        ContentValues cv = new ContentValues();
        cv.put(KEY_PRICE,price);
        cv.put(KEY_ITEM,item);
        cv.put(KEY_DETAILS,details);
        cv.put(KEY_DATE,date);
        SQLiteDatabase db = this.getWritableDatabase();
        db.insert(TABLE_RECORDS,null,cv);
    }

    public Cursor getAllRecords() {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.query(TABLE_RECORDS,null,null,null,null,null,null);
    }
    /*
    // Adding new contact
    public void addRecord(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(KEY_ID, record.getId()); // Contact Name
        values.put(KEY_PRICE, record.getPrice()); // Contact Name
        values.put(KEY_ITEM, record.getItem()); // Contact Name
        values.put(KEY_DETAILS, record.getDetails()); // Contact Name
        values.put(KEY_DATE, record.getDetails()); // Contact Phone Number

        // Inserting Row
        db.insert(TABLE_RECORDS, null, values);
        db.close(); // Closing database connection
    }
    */
    /*
    // Getting single contact
    public AlphabeticIndex.Record getRecord(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_RECORDS, new String[] { KEY_ID, KEY_PRICE,
                        KEY_ITEM, KEY_DETAILS, KEY_DATE }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        AlphabeticIndex.Record record = new AlphabeticIndex.Record(Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)), cursor.getString(2), cursor.getString(3), cursor.getString(4));
        // return contact
        return record;
    }
    */

    /*
    // Getting All Contacts
    public List<AlphabeticIndex.Record> getAllContacts() {
        List<AlphabeticIndex.Record> contactList = new ArrayList<AlphabeticIndex.Record>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_RECORDS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                AlphabeticIndex.Record record = new AlphabeticIndex.Record();
                record.setId(Integer.parseInt(cursor.getString(0)));
                record.setPrice(Integer.parseInt(cursor.getString(1)));
                record.setItem(cursor.getString(2));
                record.setDetails(cursor.getString(3));
                record.setDate(cursor.getString(4));

                // Adding contact to list
                contactList.add(record);
            } while (cursor.moveToNext());
        }

        // return contact list
        return contactList;
    }
    */

    /*
    // Getting contacts Count
    public int getRecordsCount() {
        String countQuery = "SELECT  * FROM " + TABLE_RECORDS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        // cursor.close();

        // return count
        return cursor.getCount();
    }
    */

    /*
    // Updating single contact
    public int updateContact(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, record.getId());
        values.put(KEY_PRICE, record.getPrice());
        values.put(KEY_DETAILS, record.getDetails());
        values.put(KEY_DATE, record.getDate());

        // updating row
        return db.update(TABLE_RECORDS, values, KEY_ID + " = ?",
                new String[] { String.valueOf(record.getPrice()) });
    }
    */
    /*
    // Deleting single contact
    public void deleteContact(AlphabeticIndex.Record record) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_RECORDS, KEY_ID + " = ?",new String[]
                {String.valueOf(record.getPrice()) });
        db.close();
    }
    */
}

关于 DatabaseHandler.java

更改的说明
  • rowid 别名已从 ID 更改为 _id,这是因为 CursorAdapter 需要一个名为 _id 并且该列应该是 rowid 的别名(此处不涉及技术细节)。

  • 为了方便起见,我没有使用 Record class,而是注释掉了使用此 class 的代码。

  • 我已将 TABLE 和 COLUMN 名称定义更改为 public,因此可以在其他地方访问它们。

  • 我添加了两个新方法 insertRecordgetAllRecords:-

    • insertRecord 只是为 testing/example
    • 添加一些数据
    • getAllRecords 将所有行检索为 Cursor,而不是数组。
    • 注意!数据库没有关闭,这会导致异常,因为 Cursor 需要访问数据库(无论如何打开和关闭数据库都是有害的)。

4) Activity 本身(仅在为第一个 运行 添加一些数据后显示 ListView)作为文件 MainActivity.java: -

public class MainActivity extends AppCompatActivity {

    DatabaseHandler mDBHandler;
    ListView mListView;
    SimpleCursorAdapter mSCA;
    Cursor mCsr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) this.findViewById(R.id.lv001); // Get the ListView from it's id
        mDBHandler = new DatabaseHandler(this); // Get an instance of the Database Handler

        // Add some data but only if there is no data
        if (DatabaseUtils.queryNumEntries(mDBHandler.getWritableDatabase(),DatabaseHandler.TABLE_RECORDS) < 1) {

            mDBHandler.insertRecord(100,"Rock","A large stone.","31/12/2017");
            mDBHandler.insertRecord(50,"Boulder","A Rock.","31/12/2018");
            mDBHandler.insertRecord(322,"Soil","Loose earth.","31/7/2015");
            mDBHandler.insertRecord(237,"Stone","A small rock.","31/8/2014");
            mDBHandler.insertRecord(32,"Pebble","A small smooth stone.","11/12/2017");
        }

        // get all rows into a Cursor
        mCsr = mDBHandler.getAllRecords();

        // Prepare a list of the columns to get the data from, for the ListViewt
        String[] columns_to_get_data_from = new String[]{
                DatabaseHandler.KEY_PRICE,
                DatabaseHandler.KEY_ITEM,
                DatabaseHandler.KEY_DETAILS,
                DatabaseHandler.KEY_DATE
        };

        // Prepare a list of the Views into which to place the data
        int[] itemviews_to_place_data_in = new int[]{
                R.id.record_price,
                R.id.record_item,
                R.id.record_details,
                R.id.record_date
        };

        // get and instance of SimpleCursorAdapter
        mSCA = new SimpleCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                0);
        // get and instance of SimpleCursorAdapter the listviewitem_record layout
        mListView.setAdapter(mSCA);
    }
}

结果:-

备注

这不涉及处理复选框,这可能需要一个 CustomAdapter。有很多教程,例如how do i create a custom cursor adapter for a listview for use with images and text?.

编辑修改为包括复选框处理

1) Activity 的布局 activity_main.xml - 添加了一个用于获取选中项目的按钮 :-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.budgetreport.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_margin="10dp"
        />

    <Button
        android:id="@+id/doitbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DO ALL CHECKED ROWS"
        />

    <ListView
        android:id="@+id/lv001"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

2) 自定义光标适配器 MyCustomCursorAdapter.java

  • 类似于 SimpleCursorAdapter 的签名,但带有 CheckBox.
  • id 的额外参数
  • 包括方法 getCheckedRecordIdList,它将 return 已检查的 ID 列表。
  • 在检查或未选中显示该项目的复选框时,请发出敬酒,如ListView的项目#(不是table中的项目),单击和 item [= = = 113=] 单击(如 table 中的项目值)。

:-

public class MyCustomCursorAdapter extends CursorAdapter {

    private Context mContext;
    private Cursor mCsr;
    private String[] mColumns;
    private int[] mViews;
    private int mLayout;
    private boolean[] mCheckBoxStates;
    private int mCheckBoxView;

    // Constructor for the Custom Cursor Adapter
    MyCustomCursorAdapter(Context context, int layout, Cursor csr, String[] from_columns, int[] to_views, int checkbox_view) {
        super(context,csr, false);
        mContext = context;
        mLayout = layout;
        mCsr = csr;
        mColumns = from_columns;
        mViews = to_views;
        mCheckBoxView = checkbox_view;
    }

    @Override
    // Inflate the layout we are going to use (as passed via 2nd parameter)
    public View newView(Context context, Cursor csr, ViewGroup parent) {
        // Initialise an int array for the checkboxes (all will be 0)
        mCheckBoxStates = new boolean[csr.getCount()];
        return LayoutInflater.from(context).inflate(mLayout,parent,false);
    }

    @Override
    // Tie the from_columns to the display views
    public void bindView(View view, Context context, Cursor csr) {

        // Place the data from the cursor into the respective View (TextView)
        for (int i = 0; i < mColumns.length; i++) {
            ((TextView) view.findViewById(mViews[i])).setText(csr.getString(csr.getColumnIndex(mColumns[i])));
        }
        // Set the checkbox (note should be false, unless otherwise changed)
        CheckBox currentCheckBox = (CheckBox) view.findViewById(mCheckBoxView);
        currentCheckBox.setChecked(mCheckBoxStates[mCsr.getPosition()]);
        currentCheckBox.setTag(new Long(mCsr.getLong(mCsr.getColumnIndex(DatabaseHandler.KEY_ID))));

        //
        currentCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            final int position = mCsr.getPosition();
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Store the checkbox status
                mCheckBoxStates[position] = ((CheckBox) buttonView).isChecked();
                int restore_cursor_position = mCsr.getPosition();
                //Move the Cursor to the respective row
                //NOTE! 1st position in Lisview is 1 but equates to cursor row 0 etc hence -1
                mCsr.moveToPosition(position);
                Toast.makeText(mContext,
                        "You Changed the CheckBox for row " +
                                Integer.toString(position + 1) +
                                " Item is " +
                                mCsr.getString(mCsr.getColumnIndex(DatabaseHandler.KEY_ITEM))
                        ,
                        Toast.LENGTH_SHORT
                ).show();
                //restore the Cursor's position
                mCsr.moveToPosition(restore_cursor_position);
            }
        });
    }

    // get the list of items (the ID's as long) that have been checked.
    public long[] getCheckedRecordIdList() {

        // using ArrayList as we can add as we don't yet know how many
        ArrayList<Long> rva = new ArrayList<>();
        // Just in case save the current position of the Cursor
        int restore_cursor_position = mCsr.getPosition();
        // Loop through the checkbox states
        for (int i=0; i < mCheckBoxStates.length; i++) {
            // If the checkbox reflected as being checked then handle, else ignore it
            if (mCheckBoxStates[i]) {
                // Move to the respective cursor row
                mCsr.moveToPosition(i);
                // get the respective ID and store in the arraylist
                rva.add(mCsr.getLong(mCsr.getColumnIndex(DatabaseHandler.KEY_ID)));
            }
        }
        // Done with the Cursor so re-position it
        mCsr.moveToPosition(restore_cursor_position);

        // Create the long array to be returned
        long[] rv = new long[rva.size()];
        // Populate the long array with the id's from the arraylist
        for (int i=0; i < rva.size(); i++) {
            rv[i] = rva.get(i);
        }
        // return the long[]
        return rv;
    }
}

3) 修改后的 MainActivity 以使用自定义适配器并获取已检查记录的列表(显示通过 Toast 选择的数量)- MainActivity.java

  • Changed/Added Lines/Methods 标记为 <<<<<.

:-

public class MainActivity extends AppCompatActivity {

    DatabaseHandler mDBHandler;
    ListView mListView;
    SimpleCursorAdapter mSCA;
    MyCustomCursorAdapter mMCA; // <<<<<
    Cursor mCsr;
    Button mDoItButton;
    Context mContext; //<<<<<
    long[] mCheckedIdList; //<<<<<

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        mListView = (ListView) this.findViewById(R.id.lv001); // Get the ListView from it's id
        mDoItButton = (Button) this.findViewById(R.id.doitbutton); //<<<<<
        mDBHandler = new DatabaseHandler(this); // Get an instance of the Database Handler

        // Add some data but only if there is no data
        if (DatabaseUtils.queryNumEntries(mDBHandler.getWritableDatabase(),DatabaseHandler.TABLE_RECORDS) < 1) {

            mDBHandler.insertRecord(100,"Rock","A large stone.","31/12/2017");
            mDBHandler.insertRecord(50,"Boulder","A Rock.","31/12/2018");
            mDBHandler.insertRecord(322,"Soil","Loose earth.","31/7/2015");
            mDBHandler.insertRecord(237,"Stone","A small rock.","31/8/2014");
            mDBHandler.insertRecord(32,"Pebble","A small smooth stone.","11/12/2017");
        }
        mDBHandler.increasePrice(1,213);

        // get all rows into a Cursor
        mCsr = mDBHandler.getAllRecords();

        // Prepare a list of the columns to get the data from, for the ListViewt
        String[] columns_to_get_data_from = new String[]{
                DatabaseHandler.KEY_ID,
                DatabaseHandler.KEY_PRICE,
                DatabaseHandler.KEY_ITEM,
                DatabaseHandler.KEY_DETAILS,
                DatabaseHandler.KEY_DATE
        };

        // Prepare a list of the Views into which to place the data
        int[] itemviews_to_place_data_in = new int[]{
                R.id.record_id,
                R.id.record_price,
                R.id.record_item,
                R.id.record_details,
                R.id.record_date
        };

        // get and instance of SimpleCursorAdapter the listviewitem_record layout
        mSCA = new SimpleCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                0);
        // Tie the adapter to the Listview
        mListView.setAdapter(mSCA);

        // <<<<<< Alternate Custom Cursor Adapter
        mMCA = new MyCustomCursorAdapter(this,
                R.layout.listviewitem_record,
                mCsr,
                columns_to_get_data_from,
                itemviews_to_place_data_in,
                R.id.record_checkbox //<<<<<< id of the checkbox
        );
        // Hijack the Listview
        mListView.setAdapter(mMCA); //<<<<<<

        // <<<<< DO IT BUTTON HANDLER i.e. get list of ID's for checked items
        mDoItButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get the ID's for the checked Items
                mCheckedIdList = mMCA.getCheckedRecordIdList();
                Toast.makeText(mContext,"You have " + mCheckedIdList.length + " Items checked.",Toast.LENGTH_SHORT).show();
            }
        });

    }
}
  • 注意!您通常不会有两个适配器,但我留下了 SimpleCursorAdapter 用于比较。

  • 注意!有点耐心,如果你点击太多太快,你可能会感到困惑。

注意!请参阅删除选中项目的其他答案。

根据删除选中的项目我想删除我标记的行。

这是比较容易进步的。

涉及 - a) 给数据库助手添加一个方法来根据id删除。 - b) (i) 修改 onClick 侦听器以调用 delete 方法(简单循环),然后 (ii) 更新列表视图(在循环之后)。

但是,原来的自定义适配器存在一些缺陷,即通过mCsr保留了原始光标,并且没有考虑更改(交换)Cursor时更改的复选框数。

因此,适配器已删除对 mCsr 的引用,并替换为传递的 Cursor 或通过调用 getCursor 方法。此外,swapCursor() 方法已被覆盖以调整元素的数量并重新初始化 mCheckBoxes 的 elemnets(设置为 false)。

a)新的deleteRecord方法:-

public boolean deleteRecord(long id) {
    SQLiteDatabase db = this.getWritableDatabase();
     return (db.delete(TABLE_RECORDS,KEY_ID + "=?",new String[]{Long.toString(id)})> 0);
}

b)(i) onCLickListener 修改(注意包括将所有删除分组到一个事务中):-

    // <<<<< DO IT BUTTON HANDLER i.e. get list of ID's for checked items
    mDoItButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // get the ID's for the checked Items
            mCheckedIdList = mMCA.getCheckedRecordIdList();
            Toast.makeText(mContext,"You have " + mCheckedIdList.length + " Items checked.",Toast.LENGTH_SHORT).show();
            //<<<< to delete
            SQLiteDatabase db = mDBHandler.getWritableDatabase();
            db.beginTransaction();
            for (long id: mCheckedIdList) {
                mDBHandler.deleteRecord(id);
            }
            db.setTransactionSuccessful();
            db.endTransaction();
            refreshListView();
        }
    });

b(ii) 更新 Listview(Activity 中的新方法):-

private void refreshListView() {
    mCsr = mDBHandler.getAllRecords();
    mMCA.swapCursor(mCsr);
}

注释

  • 这是作为方法添加到 activity。
  • mMCA.notifyDatasetChanged();是另一种选择(我个人更喜欢 `swapCursor1,因为它更具描述性)。

修改后的 Custom Cursor Adapter 应该是:-

public class MyCustomCursorAdapter extends CursorAdapter {

    private Context mContext;
    private String[] mColumns;
    private int[] mViews;
    private int mLayout;
    private boolean[] mCheckBoxStates;
    private int mCheckBoxView;

    // Constructor for the Custom Cursor Adapter
    MyCustomCursorAdapter(Context context, int layout, Cursor csr, String[] from_columns, int[] to_views, int checkbox_view) {
        super(context,csr, false);
        mContext = context;
        mLayout = layout;
        mColumns = from_columns;
        mViews = to_views;
        mCheckBoxView = checkbox_view;
    }

    @Override
    // Inflate the layout we are going to use (as passed via 2nd parameter)
    public View newView(Context context, Cursor csr, ViewGroup parent) {
        // Initialise an int array for the checkboxes (all will be 0)
        mCheckBoxStates = new boolean[csr.getCount()];
        return LayoutInflater.from(context).inflate(mLayout,parent,false);
    }

    @Override
    // Tie the from_columns to the display views
    public void bindView(View view, Context context, Cursor csr) {

        final Cursor fcsr = csr;

        // Place the data from the cursor into the respective View (TextView)
        for (int i = 0; i < mColumns.length; i++) {
            ((TextView) view.findViewById(mViews[i])).setText(csr.getString(csr.getColumnIndex(mColumns[i])));
        }
        // Set the checkbox (note should be false, unless otherwise changed)
        CheckBox currentCheckBox = (CheckBox) view.findViewById(mCheckBoxView);
        currentCheckBox.setChecked(mCheckBoxStates[csr.getPosition()]);
        currentCheckBox.setTag(new Long(csr.getLong(csr.getColumnIndex(DatabaseHandler.KEY_ID))));

        //
        currentCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            final int position = fcsr.getPosition();
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Store the checkbox status
                mCheckBoxStates[position] = ((CheckBox) buttonView).isChecked();
                int restore_cursor_position = fcsr.getPosition();
                //Move the Cursor to the respective row
                //NOTE! 1st position in Lisview is 1 but equates to cursor row 0 etc hence -1
                fcsr.moveToPosition(position);
                Toast.makeText(mContext,
                        "You Changed the CheckBox for row " +
                                Integer.toString(position + 1) +
                                " Item is " +
                                fcsr.getString(fcsr.getColumnIndex(DatabaseHandler.KEY_ITEM))
                        ,
                        Toast.LENGTH_SHORT
                ).show();
                //restore the Cursor's position
                fcsr.moveToPosition(restore_cursor_position);
            }
        });
    }

    // get the list of items (the ID's as long) that have been checked.
    public long[] getCheckedRecordIdList() {

        Cursor csr = this.getCursor();

        // using ArrayList as we can add as we don't yet know how many
        ArrayList<Long> rva = new ArrayList<>();
        // Just in case save the current position of the Cursor
        int restore_cursor_position = csr.getPosition();
        // Loop through the checkbox states
        for (int i=0; i < mCheckBoxStates.length; i++) {
            // If the checkbox reflected as being checked then handle, else ignore it
            if (mCheckBoxStates[i]) {
                // Move to the respective cursor row
                csr.moveToPosition(i);
                // get the respective ID and store in the arraylist
                rva.add(csr.getLong(csr.getColumnIndex(DatabaseHandler.KEY_ID)));
            }
        }
        // Done with the Cursor so re-position it
        csr.moveToPosition(restore_cursor_position);

        // Create the long array to be returned
        long[] rv = new long[rva.size()];
        // Populate the long array with the id's from the arraylist
        for (int i=0; i < rva.size(); i++) {
            rv[i] = rva.get(i);
        }
        // return the long[]
        return rv;
    }


    @Override
    public Cursor swapCursor(Cursor csr) {
        mCheckBoxStates = new boolean[csr.getCount()];
        for (int i=0; i < mCheckBoxStates.length; i++) {
            mCheckBoxStates[i] = false;
        }
        return super.swapCursor(csr);
    }
}