sql >> Database teknologi >  >> RDS >> SQLite

Sletter element fra ListView og database med OnItemClickListener

Kort sagt skal du være i stand til at skelne en række til sletning ved de data, der er tilgængelige for ListView. Hvis værdien hentes fra markøren, som 2. kolonne (dvs. strengen udtrukket ved hjælp af res.getString(1)) , og værdien bliver unik , kan du hente dette og bruge det til sletningen.

Der er dog et par problemer ved at bruge en ListAdapter vil sandsynligvis ikke være tilstrækkeligt. Der er andre adaptere, såsom en ArrayAdapter, der tilbyder flere funktioner og vigtigere en notifyDatasetChanged metode (der vil opdatere den tilknyttede ListView).

Det er spild at oprette en ny adapter for hver iteration af markøren. Så adapteren skal oprettes uden for løkken og kun én gang.

Jeg vil foreslå, at sletning ved elementklik vil være for tilbøjelig til utilsigtet klik, sletning af element LongClick ville være langt mindre tilbøjelig til utilsigtet sletning.

Hvis du flytter variable til klassevariable, behøver du ikke at erklære dem som endelige.

Så baseret på ovenstående kunne du have :-

Array Adapter-metode

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

Sammen med ovenstående er deletRow metoden er :-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • hvor
    • TB001 er en konstant streng, der er sat til tabellens navn.
    • COL_TB001_DATA er kolonnenavnet på 2. kolonne.

ADVARSEL Løsningen ovenfor vil kun fungere korrekt, hvis 2. kolonne indeholder unikke data, ellers ville flere rækker blive slettet.

Der er også den antagelse, at sletningen virker, det kunne være bedre at have :-

        @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øradaptermetode

Der er dog andre adaptere, der er egnede til markører, som kunne gøre op med behovet for et mellemliggende array. Du kan bruge en CursorAdapter . For en CursorAdapter et kolonnenavn _id er påkrævet, og denne kolonne skal være lang og identificere rækken på en uklar måde. Hensigten og dermed navnet er, at et alias for rovid bruges (derfor også hvorfor CONSTANT BaseColumns._ID findes).

Et alias for rovid oprettes ved at definere ?? INTEGER PRIMARY KEY hvor ?? er kolonnenavnet. Så ideelt set bør tabellen defineres inklusive en kolonnedefinition med _id INTEGER PRIMARY KEY for eksempel. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (du kan følge INTEGER PRIMARY KEY med søgeordet AUTOINCREMENT, men generelt ville du ikke gøre det, da det har overheads SQLite Autoincrement)

Hvis din tabel ikke har en sådan kolonne, kan du altid oprette en kolonne i markøren, når du forespørger dataene, ved at bruge rowid AS _id for eksempel. hvis din SQL svarer til SELECT * FROM mytable så kan du bruge SELECT *, rowid AS _id FROM mytable .

I dette eksempel aktien SimpleCursorAdapter vil blive brugt, kan koden være:-

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

BEMÆRK som _id kolonne vil altid være unik. Denne metode vil kun slette den specifikke række, ikke flere rækker, hvis de viste værdier ikke er unikke.



  1. Sådan fungerer Time()-funktionen i SQLite

  2. Hvad er et indeks i SQL?

  3. Hvornår skal man bruge Common Table Expression (CTE)

  4. Hvordan får jeg oplysninger om dato/klokkeslæt fra en TIMESTAMP-kolonne?