Как получить положение элемента и удалить его с помощью курсора? - PullRequest
0 голосов
/ 02 ноября 2019

Я создаю веб-приложение , которое содержит закладки Я успешно добавил элементы в listView , используя Курсор и SQLiteбаза данных , но моя проблема в том, что я не могу получить позицию элемента и удалить его. Я попытался сделать это по-своему, но получилось, что я удалил все содержимое списка. это моя MainActivity , я сделал longClickItemListener для удаления элемента списка при длинном щелчке, и это моя BookmarkDatabase

Main Activity

final Dialog bookmarksScreen = new Dialog(this);

        bookmarksScreen.requestWindowFeature(Window.FEATURE_NO_TITLE);

        bookmarksScreen.setContentView(R.layout.activity_bookmark);

        bookmarksScreen.setCancelable(true);

        final ListView listView = bookmarksScreen.findViewById(R.id.bookmark_list);
        ImageView bookmarkBack   = bookmarksScreen.findViewById(R.id.close_bookmarks);
        ImageView bookmarkDelete = bookmarksScreen.findViewById(R.id.delete_table);

        // populate an ArrayList<String> from the database and then view it
        final ArrayList<String> theList = new ArrayList<>();
        Cursor data = bookmarkDB.getListContents();
        // check if there is no data on database
        if(data.getCount() == 0){
            Log.d("Database Bookmark", "There is no items on item list");
        } else {
            while(data.moveToNext()) {
                // add data into table "COL1" and "COL2"
                theList.add(data.getString(1));
                ListAdapter listAdapter = new ArrayAdapter<>(this, R.layout.activity_listitem, theList);
                listView.setAdapter(listAdapter);
            }
        }

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

                String item = parent.getItemAtPosition(position).toString();

                webView.loadUrl(item);

                bookmarksScreen.dismiss();

            }
        });

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                final int which_item = position;

                // here i want to delete listview item

                return true;
            }
        });

        bookmarkBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bookmarksScreen.dismiss();
            }
        });

        bookmarkDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                showConfirmDialog();

                bookmarksScreen.dismiss();

            }
        });

        bookmarksScreen.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        bookmarksScreen.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);

        bookmarksScreen.show();

База данных закладок

package com.rixhion.mint.databases;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class BookmarksDatabase extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "bookmarks.db";
    public static final String TABLE_NAME = "bookmarks_data";
    public static final String COL1 = "ID";
    public static final String COL2 = "ITEM1";

    public BookmarksDatabase(Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTable = "CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, " + " ITEM1 TEXT)";
        db.execSQL(createTable);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }

    public boolean addData(String item1) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COL2, item1);

        long result = db.insert(TABLE_NAME, null, contentValues);

        //if date as inserted incorrectly it will return -1
        if (result == -1) {
            return false;
        } else {
            return true;
        }
    }
    public Cursor getListContents(){
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor data = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
        return data;
    }

    public Cursor deleteSpecificContents() {
        SQLiteDatabase db = this.getWritableDatabase();
        // Here i want to get the position of item and delete it
    }


}

1 Ответ

1 голос
/ 02 ноября 2019

В идеале вы должны использовать первичный ключ, который можно найти в ваших представлениях (или, наоборот, использовать в качестве первичного ключа значение, которое уже используется где-то для извлечения). Поскольку ваш первичный ключ здесь является полем auto_increment, нет реальной надежной корреляции между ним и представлением, которое вы пытаетесь удалить (по крайней мере из того, что я вижу в вашем коде). Один из подходов состоит в том, чтобы использовать пользовательский Adapter для своего списка, а не ArrayAdapter, и использовать методы View.setTag() и View.getTag() для хранения первичного ключа в каждом из элементов вашего Списка. Вы можете увидеть, как это сделать здесь , а также несколько интерактивных обучающих программ по адаптеру.

Если ваш макет activity_listitem имеет TextView с идентификатором text_view, где вы отображаете текст, извлеченный из вашей базы данных, и к которому вы добавили тег, хранящий первичный ключ, вы можете сделатьв вашей основной деятельности:

    listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            TextView textView = (TextView) view.findViewById(R.id.text_view);
            final Integer which_item = (Integer) textView.getTag();    //Assuming you stored the ID as an Integer
            int rowsDeleted = bookmarksDB.deleteSpecificContent(which_item);
            if(rowsDeleted == 0){  //should be 1, since we're deleting by Primary Key
                //if you would like like, handle if nothing was deleted
            }
            return true;
        }
    });

А в вашем классе BookmarksDatabase:

    public int deleteSpecificContents(int id) {
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete(TABLE_NAME, COL1 + "=?", new String[]{Integer.toString(id)});
    }


Другой подход, если вы не хотите использовать пользовательский Adapter, будетопределить элемент, который вы хотите удалить, используя его позицию в списке. Вы можете сделать это, выполнив запрос к базе данных и итерируя Cursor, пока он не совпадет с позицией вашего элемента в списке.

    listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            Cursor data = bookmarkDB.getListContents();
            int i = 0;
            while(data.moveToNext()){
                if(i == position){
                    break;
                }
                i++;
            }
            int rowsDeleted = bookmarkDB.deleteSpecificContent(data.getInt(0));
            //again, handle if rowsDeleted != 1 if you want
            return true;
        }
    });

Ваш метод BookmarkDatabase.deleteSpecificContent() точно такой же, как в первомподход к этому - единственная разница в том, как вы определяете идентификатор элемента, который будет удален. Если вы не хотите обрабатывать случай, когда deleteSpecificContent() не возвращает 1 (если я не пропускаю здесь что-то важное, то должно всегда возвращать 1 в вашем случае использования), смело изменяйте его подписьдо void, а не int.

Обратите внимание, что этот второй подход более дорогой, чем первый, поскольку он требует дополнительного запроса к базе данных и может многократно повторять Cursor. Хотя для этого требуется гораздо меньше нового / измененного кода, его использование может быть нецелесообразным (я, честно говоря, не могу сказать наверняка. Это , вероятно, хорошо для вашего случая использования, в зависимости от размера вашей базы данных, но- полное раскрытие - я не достаточно опытен с Android, чтобы сделать этот вызов. Используйте по своему усмотрению).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...