sql >> Database >  >> RDS >> SQLite

Item verwijderen uit ListView en Database met OnItemClickListener

Kortom, u moet een rij voor verwijdering kunnen onderscheiden aan de hand van de gegevens die beschikbaar zijn voor de ListView. Als de waarde opgehaald van de cursor, als de 2e kolom (d.w.z. de String geëxtraheerd met behulp van res.getString(1)) , en de waarde wordt uniek , kunt u deze ophalen en gebruiken voor de verwijdering.

Er zijn echter een paar problemen bij het gebruik van een ListAdapter zal waarschijnlijk niet voldoende zijn. Er zijn andere adapters, zoals een ArrayAdapter die meer functies biedt en vooral een notifyDatasetChanged methode (die de bijbehorende ListView zal verversen).

Het is zonde om voor elke iteratie van de cursor een nieuwe adapter te maken. Dus de adapter moet buiten de lus worden gemaakt en slechts één keer.

Ik stel voor dat het verwijderen van een itemklik te gevoelig is voor onbedoeld klikken, terwijl het verwijderen van item LongClick veel minder vatbaar is voor per ongeluk verwijderen.

Als u variabelen verplaatst om klassevariabelen te zijn, hoeft u ze niet als definitief te declareren.

Dus op basis van het bovenstaande zou je kunnen hebben:-

Array Adapter-methode

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

Samen met het bovenstaande de deletRow methode is:-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • waar
    • TB001 is een constante String die is ingesteld op de naam van de tabel.
    • COL_TB001_DATA is de kolomnaam van de 2e kolom.

WAARSCHUWING De bovenstaande oplossing werkt alleen correct als de 2e kolom unieke gegevens bevat, anders zouden meerdere rijen worden verwijderd.

Er is ook de veronderstelling dat het verwijderen werkt, het zou beter zijn om:-

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

Cursoradaptermethode

Er zijn echter andere adapters die geschikt zijn voor Cursors die de noodzaak van een tussenliggende array zouden kunnen wegnemen. U kunt een CursorAdapter . gebruiken . Voor een CursorAdapter een kolomnaam _id is vereist en deze kolom moet een lange . zijn en ook de rij uniek identificeren. De bedoeling en vandaar de naam is dat een alias van de rowid wordt gebruikt (vandaar ook waarom de CONSTANT BaseColumns._ID bestaat).

Een alias van de rowid wordt gemaakt door ?? INTEGER PRIMARY KEY waar ?? is de kolomnaam. Dus idealiter zou de tabel moeten worden gedefinieerd inclusief een kolomdefinitie met _id INTEGER PRIMARY KEY bijv. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (u kunt INTEGER PRIMARY KEY volgen met het trefwoord AUTOINCREMENT, maar over het algemeen zou u dit niet doen, omdat het overheadkosten heeft SQLite Autoincrement)

Als uw tabel niet zo'n kolom heeft, kunt u altijd een kolom in de cursor maken bij het opvragen van de gegevens, met behulp van rowid AS _id bijv. als je SQL gelijk is aan SELECT * FROM mytable dan kun je SELECT *, rowid AS _id FROM mytable . gebruiken .

In dit voorbeeld is de standaard SimpleCursorAdapter zal worden gebruikt, kan de code zijn:-

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

OPMERKING als de _id kolom zal altijd uniek zijn. Deze methode verwijdert alleen de specifieke rij en niet meerdere rijen als de weergegeven waarden niet uniek zijn.



  1. Prestatieverrassingen en aannames:STRING_SPLIT()

  2. Django-migratiefout:kolom bestaat niet

  3. De kunst van het aggregeren van gegevens in SQL van eenvoudige tot glijdende aggregaties

  4. Een Postgres DB op Heroku . vernietigen