【问题标题】:How to get position of item and delete it using Cursor?如何获取项目的位置并使用光标将其删除?
【发布时间】:2019-11-01 23:07:15
【问题描述】:

我正在制作包含 书签webview 应用程序,我使用 Cursor 成功地将项目添加到 listViewSQLite 数据库,但我的问题是我无法获得项目的 位置 并删除它我尝试以自己的方式进行操作,但我得到的是我已经删除了所有内容的列表视图。这是我的 MainActivity,我制作了一个 longClickItemListener 以在长按时删除列表视图项,这是我的 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
    }


}

【问题讨论】:

    标签: java android android-studio


    【解决方案1】:

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

    假设您的activity_listitem 布局有一个TextView,ID 为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() 方法与第一种方法完全相同 - 唯一的区别在于您如何确定要删除的项目的 id。如果您不想处理 deleteSpecificContent() 不返回 1 的情况(除非我在这里遗漏了一些重要的东西,它应该在您的用例中总是返回 1),请随时更改它签名给void,而不是int

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

    【讨论】:

    • 我解决这个问题的唯一方法是使用自定义列表视图,这对我来说更容易,因为我添加了更多的文本视图和图像来获取网站的图标,所以你的两个解决方案都是最好的,我选择了第一个导致它更容易和高效。谢谢你拯救了我的一天:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2019-09-17
    • 2012-06-14
    • 1970-01-01
    • 2018-04-14
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多