如何从 ListView 中删除项目而不从数据库中删除它?

Posted

技术标签:

【中文标题】如何从 ListView 中删除项目而不从数据库中删除它?【英文标题】:How do I delete an item from a ListView without deleting it from the database? 【发布时间】:2017-12-11 08:20:05 【问题描述】:

我在我的应用程序中实现了一个快餐栏,它有一个撤消按钮来撤消删除。目前它的工作原理是,当用户删除一个项目时,我通过从数据库执行查询来保持该项目的光标,然后从数据库中删除该项目,并通过notifyChange() 更新列表。当用户点击快餐栏上的撤消按钮时,我从保存的光标中提取内容,创建一个新的 ContentValue 并将其插入到数据库中,再次调用 notifyChange() 来更新列表。 我不喜欢这种方法。数据库操作过多。 有什么方法可以从 ListView 中删除/隐藏一个项目,并且只有在小吃栏消失时才删除该项目? 我尝试将可见性设置为 GONE 或 INVISIBLE,但这会在 ListView 中间留下一个空白区域。 我正在使用 CursorAdapter 来填充 ListView。每个列表项上都有一个 3 点菜单,显示删除选项。 这是我当前的 CursorAdapter 代码

public class ProductCursorAdapter extends CursorAdapter 

private static final String LOG_TAG = ProductCursorAdapter.class.getSimpleName();
protected ContentResolver contentResolver;

public ProductCursorAdapter(Context context, Cursor c, ContentResolver contentResolver) 
    super(context, c);
    this.contentResolver = contentResolver;


@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) 
    return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);


@Override
public void bindView(final View view, final Context context, final Cursor cursor) 
    ImageView thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
    TextView name = (TextView) view.findViewById(R.id.name);
    TextView quantity = (TextView) view.findViewById(R.id.quantity);
    TextView price = (TextView) view.findViewById(R.id.price);
    TextView supplier = (TextView) view.findViewById(R.id.supplier);

    final long id = cursor.getLong(cursor.getColumnIndexOrThrow(ProductEntry._ID));

    ImageView threeDotMenu = (ImageView) view.findViewById(R.id.three_dot_menu);
    threeDotMenu.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            PopupMenu popup = new PopupMenu(context, v);
            popup.getMenuInflater().inflate(R.menu.list_item_context_menu, popup.getMenu());
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() 
                @Override
                public boolean onMenuItemClick(MenuItem item) 
                    switch (item.getItemId()) 
                        case R.id.context_delete_product:
                            //the uri of the product we're deleting
                            Uri currentProductUri = ContentUris.withAppendedId(ProductEntry.CONTENT_URI, id);
                            //What to extract from the database
                            String[] projection = 
                                    ProductEntry._ID,
                                    ProductEntry.COLUMN_NAME,
                                    ProductEntry.COLUMN_QUANTITY,
                                    ProductEntry.COLUMN_PRICE,
                                    ProductEntry.COLUMN_SUPPLIER,
                                    ProductEntry.COLUMN_IMAGE
                            ;
                            //retrieve the product from the database before deleting in case
                            //we need to restore it later
                            Cursor cursor = contentResolver.query(currentProductUri,
                                    projection,
                                    null,
                                    null,
                                    null,
                                    null);
                            cursor.moveToFirst();
                            Snackbar snackbar = Snackbar.make(view.getRootView().findViewById(R.id.coordinator_layout), "Product Deleted", Snackbar.LENGTH_LONG);
                            snackbar.setAction("Undo", new MyUndoListener(cursor));
                            snackbar.show();
                            contentResolver.delete(currentProductUri, null, null);
                            return true;
                        default:
                            return false;
                    
                
            );
            popup.show();
        
    );


    . . .




public class MyUndoListener implements View.OnClickListener 
    Cursor cursor = null;

    public MyUndoListener(Cursor cursor) 
        this.cursor = cursor;

    

    @Override
    public void onClick(View v) 
        contentResolver.insert(ProductEntry.CONTENT_URI, extractFromCursor(cursor));
    

    private ContentValues extractFromCursor(Cursor cursor) 

        int id = cursor.getInt(cursor.getColumnIndexOrThrow(ProductEntry._ID));

        String name = cursor.getString(cursor.getColumnIndexOrThrow(ProductEntry.COLUMN_NAME));

        int quantity = cursor.getInt(cursor.getColumnIndexOrThrow(ProductEntry.COLUMN_QUANTITY));

        int price = cursor.getInt(cursor.getColumnIndexOrThrow(ProductEntry.COLUMN_PRICE));

        String supplier = cursor.getString(cursor.getColumnIndexOrThrow(ProductEntry.COLUMN_SUPPLIER));

        byte[] image = cursor.getBlob(cursor.getColumnIndexOrThrow(ProductEntry.COLUMN_IMAGE));
        ContentValues value = new ContentValues();
        value.put(ProductEntry._ID, id);
        value.put(ProductEntry.COLUMN_NAME, name);
        value.put(ProductEntry.COLUMN_PRICE, price);
        value.put(ProductEntry.COLUMN_QUANTITY, quantity);
        value.put(ProductEntry.COLUMN_SUPPLIER, supplier);
        value.put(ProductEntry.COLUMN_IMAGE, image);
        cursor.close();
        return value;

    


【问题讨论】:

在表中添加一个名为“deleted”的布尔类型的列,如果删除则为true,否则为false,并且只显示那些删除值为false的记录。 【参考方案1】:

尼山好了,为此制作数据库值的Arraylist,然后绑定一个listview。每当您想删除一个项目(不是从您的数据库中)时,然后复制没有该项目的 arraylist 并再次绑定列表视图。

因此您的数据库保持不变,您可以在撤消的情况下再次使用它。 那么你想删除什么项目,从原来的arraylst中绑定一个新的arraylist,然后使用它。

【讨论】:

CursorAdapter 不能这样工作。它依赖于数据库游标而不是列表。

以上是关于如何从 ListView 中删除项目而不从数据库中删除它?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2:禁用输入字段而不从表单组中删除?

在rake测试中排除gem警告而不从自己的代码中删除警告

拖放而不从所有者中删除

从 UICollectionView 中删除单元格而不从顶部重新加载 [关闭]

<canvas>:从内存中删除 2d 上下文而不从内存中删除 webgl 上下文

在 SVN 中不提交行)而不从文件中删除它们?