【问题标题】:Deleting listview row with SQLite data by click通过单击删除带有 SQLite 数据的列表视图行
【发布时间】:2017-09-21 19:22:34
【问题描述】:

我正在尝试通过单击删除包含 SQLite 数据的列表视图行。

当我按下列表视图项时,没有任何反应,日志中没有错误。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_meal);

    userList = (ListView) findViewById(R.id.listView8);

    mHelper = new DbHelper(this);
    userList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            dataBase.delete(DbHelper.TABLE_NAME, DbHelper.MEAL_ID + "=" + mealId.get(arg2), null);
            displayData();
        }
    });

    private void displayData() {
        dataBase = mHelper.getWritableDatabase();
        Cursor mCursor = dataBase.rawQuery("SELECT * FROM "+ DbHelper.TABLE_NAME, null);
        mealId.clear();
        mealName.clear();
        if (mCursor.moveToFirst()) {
            do {
                mealId.add(mCursor.getString(mCursor.getColumnIndex(DbHelper.MEAL_ID)));
                mealName.add(mCursor.getString(mCursor.getColumnIndex(DbHelper.MEAL_NAME)));
            } while (mCursor.moveToNext());
        }
        DisplayAdapter disadpt = new DisplayAdapter(NewMealActivity.this, mealId, mealName);
        userList.setAdapter(disadpt);
        mCursor.close();
    }
}

【问题讨论】:

  • 请提供更多信息。你的点击监听器被调用了吗?为什么您每次都更改适配器而不是仅更新光标。只需清除列表,添加新项目并在活动适配器上调用 notifyDataSetChanged。没有理由每次都重新创建。您的删除代码也有效吗?它应该返回“long for num rows deleted”你会返回“1”吗?

标签: android sqlite listview


【解决方案1】:

我认为您的问题是 arg2 是列表中的位置,不等于显示的行的 id。

也就是说,如果您选择第一个项目,那么它的位置,因此 arg2 将是 0

假设您在 id 列中使用 INTEGER PRIMARY KEYINTEGER PRIMARY KEY AUTOINCREMENT,那么第一个 ID 可能是 1,接下来是 2 等等(但是您永远不应该依赖它,例如,如果行被删除,那么该 id 很可能不会被重新使用并且序列被破坏)。

如果列表视图使用 CursorAdapter,

arg3 将具有 id BUT ONLY (我建议这样做,因为那时您不需要中间数组,刷新列表只需重建光标并使用swapCursornotifyOnDatasetChanged,我更喜欢前者,因为它更具描述性)。

PS 如果您确实使用 CursorAdapter,则 id 列必须被称为 _id(有一些方法可以通过 SELECT 查询中的 AS 重命名/创建列,但 imo 最好使用 _id 作为表中的列名)。

正如我昨天回答了一个非常相似的问题(更新而不是删除),我将向您指出 How can i update a field of my spinner with user input in EditText


具体答案:

您可以进行以下更改(当您将 ID 列提取到数组中时):-

换行

        dataBase.delete(DbHelper.TABLE_NAME,
                DbHelper.MEAL_ID + "=" + mealId.get(arg2), null);

        dataBase.delete(DbHelper.TABLE_NAME,DbHelper.MEAL_ID + "=" +
                    mealId.get(arg2),null);

因此,您使用 position 作为 mealId 数组的索引,该数组具有正确的 ID。


注意!理想情况下,mealId 应该是 Long 而不是字符串,那么上面的内容将是:-

        dataBase.delete(DbHelper.TABLE_NAME,DbHelper.MEAL_ID + "=" +
                    Long.toString(mealId.get(arg2)),null);

随着

        mealName.add(mCursor.getString(mCursor.getColumnIndex(DbHelper.MEAL_NAME)));

被改成

        mealName.add(mCursor.getLong(mCursor.getColumnIndex(DbHelper.MEAL_NAME)));

比较 ArrayAdapter 和 CursorAdapter 的工作示例

这与使用 ArrayAdpater 的代码非常相似(DBHlper 应该接近反映您的代码(至少对于相关/使用的列而言))

注意!使用 ArrayAdapter 而不是 DisplayAdapter(我猜是自定义适配器)。

:-

类变量:-

    DbHelper mHelper;
    SQLiteDatabase dataBase;
    ArrayList<String> mealName = new ArrayList<>();
    ArrayList<Long> mealId = new ArrayList<>();
    ArrayAdapter<String> arrayAdapter;
    SimpleCursorAdapter sca;
    Cursor mCursor2;

Activity 的onCreate 中的代码(或由onCreate 调用):-

    mHelper = new DbHelper(this);
    userList = (ListView) findViewById(R.id.listview);
    userList2 = (ListView) findViewById(R.id.listview2);


    // Add some data (note will add rows each time this is run)
    mHelper.insertMeal("Fish");
    mHelper.insertMeal("Beef");
    mHelper.insertMeal("Lamb");
    mHelper.insertMeal("Rice");


    // Array method
    // Looks shorter but relies upon code if displayData
    userList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            dataBase.delete(DbHelper.TABLE_NAME,DbHelper.MEAL_ID + "=" +
                    Long.toString(mealId.get(i)),null);
            displayData();
        }
    });

    // Alternative using Cursor Adapter and thus long l (4th parameter) (the ID)
    // No Need for intermediate arrays, uses the cursor directly
    // (Only calls displayData to sync lists)
    userList2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            dataBase.delete(DbHelper.TABLE_NAME,DbHelper.MEAL_ID + "=" +
            Long.toString(l),null);
            mCursor2 = dataBase.query(DbHelper.TABLE_NAME,null,null,null,null,null,null);
            sca.swapCursor(mCursor2);
            // keep userList in sync with userList2
            displayData();
        }
    });

    //Initial setup of userList2
    dataBase = mHelper.getWritableDatabase();
    mCursor2 = dataBase.query(DbHelper.TABLE_NAME,null,null,null,null,null,null);
    sca = new SimpleCursorAdapter(this,
            android.R.layout.simple_list_item_1,
            mCursor2,
            new String[] {DbHelper.MEAL_NAME},
            new int[] {android.R.id.text1},
            0
    );
    userList2.setAdapter(sca);

    //Initial setup of userList
    displayData();
}

displayData 方法(只有 ArrayAdpater 真正需要,而不是调用它来同步两个列表):-

private void displayData() {
    dataBase = mHelper.getWritableDatabase();
    Cursor mCursor = dataBase.rawQuery("SELECT * FROM " + DbHelper.TABLE_NAME,null);
    mealId.clear();
    mealName.clear();
    while (mCursor.moveToNext()) {
        mealId.add(mCursor.getLong(mCursor.getColumnIndex(DbHelper.MEAL_ID)));
        mealName.add(mCursor.getString(mCursor.getColumnIndex(DbHelper.MEAL_NAME)));
        arrayAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_selectable_list_item,
                mealName
        );
        userList.setAdapter(arrayAdapter);
    }
    // keep userlist 2 in sync userList
    mCursor2 = mCursor; // cheat by using userList's cursor
    sca.swapCursor(mCursor2);
}

示例展示:-

Left列表(ArrayAdapter)中点击Lamb(第一项)后:-

点击列表(CursorAdapter)中的Beef(现在是第3项)后:-

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多