使用OnItemClickListener从ListView和数据库中删除项目

时间:2018-06-09 14:12:57

标签: android sqlite listview android-sqlite

我创建了一个数据库并设法将添加的项目显示到ListView中。现在我需要一种从ListView和数据库中删除项目的方法。

public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        myDb = new DatabaseHelper(this);
        ListView listViewFaecher = (ListView) findViewById(R.id.listViewFaecher);

        final ArrayList<String> faecherListe = new ArrayList<>();
        Cursor res = myDb.zeigeFaecher();

        if (res.getCount() == 0){
            Toast.makeText(ZeigeFaecherListe.this, "Keine Fächer gefunden", Toast.LENGTH_LONG).show();
        } else {
            while (res.moveToNext()){
                faecherListe.add(res.getString(1));
                ListAdapter fachListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, faecherListe);
                listViewFaecher.setAdapter(fachListAdapter);
            }
        }

        listViewFaecher.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {

            }
        });
    }
}

2 个答案:

答案 0 :(得分:1)

简而言之,您需要能够通过ListView可用的数据区分要删除的行。如果从游标中检索到的值,作为第二列(即使用res.getString(1))提取的字符串,,并且该值将是唯一的,则可以检索此值并将其用于删除。

但是,有一些问题,使用ListAdapter可能还不够。还有其他适配器,例如提供更多功能的ArrayAdapter,重要的是 notifyDatasetChanged 方法(将刷新关联的ListView)。

为游标的每次迭代创建一个新的适配器是一种浪费。所以适配器应该在循环之外创建,只需要创建一次。

我建议删除项目点击将太容易意外点击,删除项目LongClick将不太容易被意外删除。

如果将变量移动为类变量,则不必将它们声明为最终变量。

基于以上所述,您可以: -

数组适配器方法

public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;
    Cursor res;
    ListView listViewFaecher;
    ArrayAdapter<String> fachListAdapter;
    ArrayList<String> faecherListe;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        listViewFaecher = (ListView) this.findViewById(R.id.listview);
        myDb = new DatabaseHelper(this);
        addSomeData(); //<<<<<<<<<< ADDED for testing

        faecherListe = new ArrayList<>();
        res = myDb.zeigeFaecher();
        while (res.moveToNext()) {
            faecherListe.add(res.getString(1));
        }

        //<<<< NOTE outside of the loop as this only needs to be done once
        fachListAdapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                faecherListe
        );
        listViewFaecher.setAdapter(fachListAdapter);

        //<<<<< NOTE used LONG CLICK listener (less likely to accidentally delete)
        listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                myDb.deleteRow((String)fachListAdapter.getItem(position));
                faecherListe.remove(position);
                fachListAdapter.notifyDataSetChanged(); 
                return true; //<<<< Indicate that this longclick has been used
            }
        });
    }

    private void addSomeData() {
        for (int i=1; i <= 10; i++) {
            myDb.addRow("Row " + String.valueOf(i));
        }
    }
}

除此之外, deletRow 方法是: -

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • ,其中
    • TB001 是一个常量字符串,它设置为表格的名称。
    • COL_TB001_DATA 是第二列的列名。

警告上述解决方案仅在第二列包含唯一数据时才能正常工作,否则将删除多行。

还有一个假设是删除有效,最好有: -

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            if (myDb.deleteRow((String)fachListAdapter.getItem(position))<0) {
                faecherListe.remove(position);
            }
            fachListAdapter.notifyDataSetChanged(); 
            return true; //<<<< Indicate that this longclick has been used
        }

光标适配器方法

但是,还有其他适合游标的适配器可以消除对中间阵列的需求。您可以使用 CursorAdapter 。对于 CursorAdapter ,列名称 _id 是必需的,此列应为,并且还无法识别行。意图和名称是使用 rowid 的别名(因此也存在CONSTANT BaseColumns._ID 的原因。)

rowid 的别名是通过定义?? INTEGER PRIMARY KEY来创建的?是列名。理想情况下,应该定义表格,包括使用_id INTEGER PRIMARY KEY的列定义,例如CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (您可以使用关键字AUTOINCREMENT关注INTEGER PRIMARY KEY,但通常您不会这样做,因为它有开销SQLite Autoincrement

如果您的表没有这样的列,那么您可以在查询数据时始终使用rowid AS _id创建一个列。如果SQL等于SELECT * FROM mytable,那么您可以使用SELECT *, rowid AS _id FROM mytable

在此示例中,将使用股票 SimpleCursorAdapter ,代码可以是: -

public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;
    Cursor res;
    ListView listViewFaecher;
    SimpleCursorAdapter fachSimpleCursorAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        listViewFaecher = (ListView) this.findViewById(R.id.listview);
        myDb = new DatabaseHelper(this);
        addSomeData(); //<<<<<<<<<< ADDED for testing

        faecherListe = new ArrayList<>();
        res = myDb.zeigeFaecher();
        fachSimpleCursorAdapter = new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1, //<<<< The layout
                res, //<<<< The Cursor
                new String[]{"_data"}, //<<<< The column names from which to get the data
                new int[]{android.R.id.text1} //<<<< The ids of the views in which the data is placed
                );
        listViewFaecher.setAdapter(fachSimpleCursorAdapter);
        listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                // id is the value of the respective _id column
                //<<<< Normally you would have the delete method in the Databasehelper >>>>
                myDb.getWritableDatabase().delete("mytable","_id=?",new String[]{String.valueOf(id)});
                fachSimpleCursorAdapter.swapCursor(myDb.zeigeFaecher()); // Tell the adapter about the new cursor
                return true;
            }
        });
    }
}

注意,因为 _id 列始终是唯一的,如果显示的值不唯一,此方法将仅删除特定行而不删除多行。< / p>

答案 1 :(得分:-1)

listViewFaecher.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {

         // Call delete method here by passing position
         //position will contain the position of item clicked by the user.
     }
});