SQLite
 sql >> база данни >  >> RDS >> SQLite

Изтриване на елемент от ListView и база данни с OnItemClickListener

Накратко, трябва да можете да различите ред за изтриване по данните, налични за ListView. Ако стойността е извлечена от курсора, като 2-ра колона (т.е. низът, извлечен с помощта на res.getString(1)) ,и стойността ще бъде уникална , можете да извлечете това и да го използвате за изтриването.

Има обаче няколко проблема при използване на ListAdapter вероятно няма да е достатъчно. Има и други адаптери, като ArrayAdapter, които предлагат повече функции и най-важното notifyDatasetChanged метод (който ще опресни свързания ListView).

Създаването на нов адаптер за всяка итерация на курсора е загуба. Така че адаптерът трябва да бъде създаден извън цикъла и само веднъж.

Предполагам, че изтриването на щракване върху елемент ще бъде твърде податливо на случайно щракване, изтриването на елемент LongClick би било далеч по-малко податливо на случайно изтриване.

Ако преместите променливи, за да бъдат променливи на клас, не е нужно да ги декларирате като окончателни.

Така че въз основа на горното, можете да имате :-

Метод на адаптера на масив

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

Заедно с горното deletRow методът е :-

public int deleteRow(String col2) {
    SQLiteDatabase db = this.getWritableDatabase();
    return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
  • къде
    • TB001 е константен низ, който е зададен на името на таблицата.
    • COL_TB001_DATA е името на колоната на 2-ра колона.

ПРЕДУПРЕЖДЕНИЕ Решението по-горе ще работи правилно само ако 2-та колона съдържа уникални данни, в противен случай множество редове ще бъдат изтрити.

Има също така предположението, че изтриването работи, може да е по-добре да имате :-

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

Метод на адаптера на курсора

Има обаче и други адаптери, подходящи за курсори, които могат да премахнат необходимостта от междинен масив. Можете да използвате CursorAdapter . За CursorAdapter име на колона _id е задължителен и тази колона трябва да е дълга и също така неправилно идентифициране на реда. Намерението и оттам името е псевдоним на rowid се използва (следователно и защо CONSTANT BaseColumns._ID съществува).

Псевдоним на rowid се създава чрез дефиниране на ?? INTEGER PRIMARY KEY където ?? е името на колоната. Така че в идеалния случай таблицата трябва да бъде дефинирана, включително дефиниция на колона с _id INTEGER PRIMARY KEY напр. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT) (можете да следвате INTEGER PRIMARY KEY с ключовата дума AUTOINCREMENT, но обикновено не бихте го направили, тъй като има допълнителни разходи за SQLite Autoincrement)

Ако вашата таблица няма такава колона, винаги можете да създадете колона в курсора при запитване на данните, като използвате rowid AS _id напр. ако SQL се равнява на SELECT * FROM mytable тогава можете да използвате SELECT *, rowid AS _id FROM mytable .

В този пример стандартният SimpleCursorAdapter ще се използва, кодът може да бъде :-

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

ЗАБЕЛЕЖКА като _id колоната винаги ще бъде уникална, този метод ще изтрие само конкретния ред, а не множество редове, ако показаните стойности не са уникални.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. GreenDao freemaker.jar липсва

  2. Върнете списък с външни ключове в SQLite

  3. Как да предавам данни от дейност към java клас

  4. Коригиране на грешка:„Избиранията отляво и отдясно на UNION нямат същия брой колони с резултати“ в SQLite

  5. Android:Грешка при копиране на база данни (Sqliite) от папка с активи