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.