首页 > 解决方案 > 如何获取项目的位置并使用光标将其删除?

问题描述

我正在制作包含书签的webview应用程序我使用CursorSQLite 数据库成功地将项目添加到listView但我的问题是我无法获取项目的位置并删除它我试图以我自己的方式做到这一点但我得到的是我已经删除了列表视图的所有内容。这是我的MainActivity,我做了一个longClickItemListener以在长按时删除 listview 项目,这是我的BookmarkDatabase

主要活动

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
    }


}

标签: javaandroidandroid-studio

解决方案


理想情况下,您将在视图中可检索的某处使用主键(或者,反之亦然,用作主键,该值已在可检索的某处使用)。由于您的主键是一个auto_increment字段,因此它与您尝试删除的视图之间没有真正可靠的关联(至少从我在您的代码中可以看到的)。一种方法是Adapter为您的列表使用自定义,而不是使用ArrayAdapter, 并使用View.setTag()andView.getTag()方法将主键存储在列表的每个项目上。您可以在此处查看如何执行此操作,以及几个在线自定义适配器教程。

假设您的activity_listitem布局有一个TextViewwith id text_view,您可以在其中显示从数据库中获取的文本,并且您已经添加了存储主键的标签,您可以在 Main Activity 中执行以下操作:

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


如果您不想使用 custom 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()方法与第一种方法完全相同 - 唯一的区别在于您如何确定要删除的项目的 id。如果您不想处理deleteSpecificContent()不返回 1 的情况(除非我在这里遗漏了一些重要的东西,否则在您的用例中它应该始终返回 1),请随意将其签名更改为void,而不是int.

请注意,第二种方法比第一种方法更昂贵,因为它需要额外的数据库查询,并且可以迭代Cursor很多。虽然它需要的新代码/更改代码要少得多,但可能不建议使用(老实说,我不能肯定地说。这可能适合您的用例,具体取决于数据库的大小,但是 - 完全披露 - 我是没有足够的 Android 经验来拨打这个电话。请自行决定使用)。


推荐阅读