sql >> Databasteknik >  >> RDS >> SQLite

Tar bort objekt från ListView och Database med OnItemClickListener

Kort sagt måste du kunna särskilja en rad för radering med den information som är tillgänglig för ListView. Om värdet hämtas från markören, som den andra kolumnen (d.v.s. strängen extraherad med res.getString(1)) , och värdet kommer att vara unikt , du kan hämta detta och använda det för raderingen.

Det finns dock några problem när du använder en ListAdapter kommer förmodligen inte att räcka. Det finns andra adaptrar, till exempel en ArrayAdapter som erbjuder fler funktioner och viktigare än en notifyDatasetChanged metod (som kommer att uppdatera den associerade ListView).

Det är ett slöseri att skapa en ny adapter för varje iteration av markören. Så adaptern bör skapas utanför slingan och bara en gång.

Jag skulle föreslå att radering vid objektklick kommer att vara för benäget att oavsiktligt klicka, borttagning av objekt LongClick skulle vara mycket mindre benäget att raderas oavsiktligt.

Om du flyttar variabler till klassvariabler behöver du inte deklarera dem som slutgiltiga.

Så baserat på ovanstående kan du ha :-

Array Adapter-metod

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

Tillsammans med ovanstående deletRow Metoden är :-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • var
    • TB001 är en konstant sträng som är satt till tabellens namn.
    • COL_TB001_DATA är kolumnnamnet för den andra kolumnen.

VARNING Lösningen ovan kommer bara att fungera korrekt om den andra kolumnen innehåller unika data, annars skulle flera rader raderas.

Det finns också antagandet att raderingen fungerar, det kan vara bättre att ha :-

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

Marköradaptermetod

Det finns dock andra adaptrar som är lämpade för Cursors som skulle kunna eliminera behovet av en mellanliggande array. Du kan använda en CursorAdapter . För en CursorAdapter ett kolumnnamn _id krävs och den här kolumnen ska vara lång och även otydligt identifiera raden. Avsikten och därav namnet är att ett alias för rovid används (därav också varför CONSTANT BaseColumns._ID finns).

Ett alias för rovid skapas genom att definiera ?? INTEGER PRIMARY KEY var ?? är kolumnnamnet. Så helst borde tabellen definieras inklusive en kolumndefinition med _id INTEGER PRIMARY KEY t.ex. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (du kan följa INTEGER PRIMARY KEY med nyckelordet AUTOINCREMENT, men vanligtvis skulle du inte göra det, eftersom det har omkostnader SQLite Autoincrement)

Om din tabell inte har en sådan kolumn kan du alltid skapa en kolumn i markören när du frågar efter data, genom att använda rowid AS _id t.ex. om din SQL motsvarar SELECT * FROM mytable sedan kan du använda SELECT *, rowid AS _id FROM mytable .

I detta exempel aktien SimpleCursorAdapter kommer att användas kan koden vara :-

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

OBS som _id kolumnen kommer alltid att vara unik. Denna metod tar bara bort den specifika raden, inte flera rader om de visade värdena inte är unika.



  1. Hur man hämtar datumet från en Datetime-kolumn i MySQL

  2. Hur man ökar Max anslutningar i MySQL

  3. Hur man skapar en användare med pgAdmin

  4. rs.last() ger Ogiltig operation för enbart forward-resultatuppsättning:last