sql >> Databáze >  >> RDS >> SQLite

Odstranění položky z ListView a databáze pomocí OnItemClickListener

Stručně řečeno, musíte být schopni rozlišit řádek pro smazání podle dat dostupných pro ListView. Pokud je hodnota načtena z kurzoru, jako 2. sloupec (tj. řetězec extrahovaný pomocí res.getString(1)) , a hodnota bude jedinečná , můžete jej načíst a použít ke smazání.

Při použití ListAdapter však existuje několik problémů asi nebude dostačující. Existují další adaptéry, jako je ArrayAdapter, které nabízejí více funkcí, a co je důležité, notifyDatasetChanged metoda (která obnoví související ListView).

Je zbytečné vytvářet nový adaptér pro každou iteraci kurzoru. Adaptér by tedy měl být vytvořen mimo smyčku a pouze jednou.

Navrhoval bych, že smazání po kliknutí na položku bude příliš náchylné k náhodnému kliknutí, smazání na položce LongClick by bylo mnohem méně náchylné k náhodnému smazání.

Pokud přesunete proměnné jako proměnné třídy, nemusíte je deklarovat jako konečné.

Takže na základě výše uvedeného byste mohli mít :-

Metoda adaptéru pole

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

Spolu s výše uvedeným deletRow metoda je :-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • kde
    • TB001 je konstantní řetězec, který je nastaven na název tabulky.
    • COL_TB001_DATA je název sloupce 2. sloupce.

UPOZORNĚNÍ Výše uvedené řešení bude správně fungovat pouze v případě, že 2. sloupec obsahuje jedinečná data, jinak by bylo odstraněno více řádků.

Je zde i předpoklad, že mazání funguje, mohlo by být lepší mít :-

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

Metoda kurzorového adaptéru

Existují však další adaptéry vhodné pro kurzory, které by mohly odstranit potřebu mezilehlého pole. Můžete použít CursorAdapter . Pro CursorAdapter název sloupce _id je povinný a tento sloupec by měl být dlouhý a také nesprávně identifikovat řádek. Záměr a odtud název je, že jde o alias rowid se používá (proto také CONSTANT BaseColumns._ID existuje).

Alias ​​rowid je vytvořeno definováním ?? INTEGER PRIMARY KEY kde?? je název sloupce. V ideálním případě by tedy měla být tabulka definována včetně definice sloupce s _id INTEGER PRIMARY KEY např. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (můžete postupovat podle INTEGER PRIMARY KEY s klíčovým slovem AUTOINCREMENT, nicméně obecně byste to neudělali, protože má režii SQLite Autoincrement)

Pokud vaše tabulka takový sloupec nemá, můžete při dotazování na data vždy vytvořit sloupec v kurzoru pomocí rowid AS _id např. pokud se SQL rovná SELECT * FROM mytable pak můžete použít SELECT *, rowid AS _id FROM mytable .

V tomto příkladu SimpleCursorAdapter bude použit, kód může být :-

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

POZNÁMKA jako _id sloupec bude vždy jedinečný, tato metoda odstraní pouze konkrétní řádek, nikoli více řádků, pokud zobrazené hodnoty nejsou jedinečné.



  1. Jak nastavit cílový adresář archivních protokolů v databázi Oracle

  2. Identifikace a správa kritických přístupových aplikací během vývojového projektu

  3. Divize ( / ) nedává mou odpověď v postgresql

  4. Analýza dat QuickBooks v Dundas BI