Удаление элемента из ListView и базы данных с помощью OnItemClickListener - PullRequest
0 голосов
/ 09 июня 2018

Я создал базу данных и сумел отобразить добавленные элементы в ListView.Теперь мне нужен метод для удаления элемента из ListView и базы данных.

public class ZeigeFaecherListe extends AppCompatActivity {

    DatabaseHelper myDb;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.zeige_faecher);

        myDb = new DatabaseHelper(this);
        ListView listViewFaecher = (ListView) findViewById(R.id.listViewFaecher);

        final ArrayList<String> faecherListe = new ArrayList<>();
        Cursor res = myDb.zeigeFaecher();

        if (res.getCount() == 0){
            Toast.makeText(ZeigeFaecherListe.this, "Keine Fächer gefunden", Toast.LENGTH_LONG).show();
        } else {
            while (res.moveToNext()){
                faecherListe.add(res.getString(1));
                ListAdapter fachListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, faecherListe);
                listViewFaecher.setAdapter(fachListAdapter);
            }
        }

        listViewFaecher.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {

            }
        });
    }
}

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Короче говоря, вам нужно уметь различать строку для удаления по данным, доступным для 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));
        }
    }
}

Наряду с этимe над методом 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Автоинкремент )

Если в вашей таблице нет такого столбца, вы всегда можете создать столбец в курсоре при запросе данных, используя 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;
            }
        });
    }
}

NOTE , поскольку столбец _id всегда будет уникальным. Этот метод удаляет только определенную строку, а не несколько строк, если отображаемые значения не являются уникальными.

0 голосов
/ 09 июня 2018
listViewFaecher.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {

         // Call delete method here by passing position
         //position will contain the position of item clicked by the user.
     }
});
...