SQLite
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> SQLite

Xóa mục khỏi ListView và Cơ sở dữ liệu bằng OnItemClickListener

Tóm lại, bạn cần có khả năng phân biệt một hàng để xóa bằng dữ liệu có sẵn cho ListView. Nếu giá trị được truy xuất từ ​​con trỏ, dưới dạng cột thứ 2 (tức là Chuỗi được trích xuất bằng cách sử dụng res.getString(1)) , và giá trị sẽ là duy nhất , bạn có thể lấy nó và sử dụng nó để xóa.

Tuy nhiên, có một số vấn đề khi sử dụng ListAdapter có lẽ sẽ không đủ. Có những bộ điều hợp khác, chẳng hạn như ArrayAdapter cung cấp nhiều tính năng hơn và quan trọng là notifyDatasetChanged (sẽ làm mới ListView được liên kết).

Thật lãng phí khi tạo một bộ điều hợp mới cho mỗi lần lặp lại con trỏ. Vì vậy, bộ điều hợp nên được tạo bên ngoài vòng lặp và chỉ một lần.

Tôi đề nghị rằng xóa khi nhấp vào mục sẽ quá dễ bị nhấp vào tình cờ, xóa trên LongClick mục sẽ ít bị xóa do tình cờ hơn nhiều.

Nếu bạn di chuyển các biến thành biến lớp, bạn không cần phải khai báo chúng là biến cuối cùng.

Vì vậy, dựa trên những điều trên, bạn có thể có:-

Phương thức Bộ điều hợp mảng

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));
        }
    }
}

Cùng với deletRow ở trên phương pháp là:-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • ở đâu
    • TB001 là một chuỗi không đổi thatis được đặt thành tên của bảng.
    • COL_TB001_DATA là tên cột của cột thứ 2.

CẢNH BÁO Giải pháp trên sẽ chỉ hoạt động chính xác nếu cột thứ 2 chứa dữ liệu duy nhất, nếu không nhiều hàng sẽ bị xóa.

Cũng có giả định rằng việc xóa hoạt động, tốt hơn nên có:-

        @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
        }

Phương thức Bộ điều hợp con trỏ

Tuy nhiên, có những bộ điều hợp khác phù hợp với Con trỏ có thể loại bỏ nhu cầu về Mảng trung gian. Bạn có thể sử dụng CursorAdapter . Đối với CursorAdapter tên cột _id là bắt buộc và cột này phải là dài và cũng xác định hàng một cách khó hiểu. Ý định và do đó tên là một bí danh của người hàng xóm được sử dụng (do đó cũng là lý do CONSTANT BaseColumns._ID tồn tại).

Bí danh của rowid được tạo bằng cách xác định ?? INTEGER PRIMARY KEY ở đâu ?? là tên cột. Vì vậy, lý tưởng nhất là bảng nên được xác định bao gồm định nghĩa cột với _id INTEGER PRIMARY KEY ví dụ. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (bạn có thể theo dõi INTEGER PRIMARY KEY với từ khóa AUTOINCREMENT, tuy nhiên thông thường bạn sẽ không làm như vậy, vì nó có chi phí tự động tăng SQLite)

Nếu bảng của bạn không có cột như vậy thì bạn luôn có thể tạo một cột trong con trỏ khi truy vấn dữ liệu, bằng cách sử dụng rowid AS _id ví dụ. nếu bạn SQL tương đương với SELECT * FROM mytable thì bạn có thể sử dụng SELECT *, rowid AS _id FROM mytable .

Trong ví dụ này, kho SimpleCursorAdapter sẽ được sử dụng, mã có thể là:-

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;
            }
        });
    }
}

LƯU Ý dưới dạng _id cột sẽ luôn là duy nhất phương pháp này sẽ chỉ xóa hàng cụ thể chứ không phải nhiều hàng nếu các giá trị được hiển thị không phải là duy nhất.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nhận ngày thứ Hai đầu tiên của tháng trong SQLite

  2. Kết nối SQLite bị rò rỉ mặc dù mọi thứ đã đóng lại

  3. java.lang.IllegalArgumentException:cột '_id' không tồn tại

  4. Có thực sự cần thiết để tạo bảng SQLite mỗi khi ứng dụng khởi động?

  5. Không thể tải cơ sở dữ liệu sqlite trong lần chạy đầu tiên