【问题标题】:Deleting items in ListView using intent使用意图删除 ListView 中的项目
【发布时间】:2015-05-14 20:17:18
【问题描述】:

我的问题是我试图从 ListView 中删除项目,为此我在 CustomAdapter 中有一个按钮。

我将此按钮设置为 onClickListener 并尝试使用 Intent 将项目名称传递给主要活动。

在 Main 中,当收到名为“deleteProduct”的意图时,调用方法 deleteProduct,在此方法中,我试图将要删除的产品名称传递给数据库。

我的自定义适配器:

private DbItemDeleteListener deleteListener;

CustomAdapter(Context context, ArrayList<Product> productNames,DbItemDeleteListener deleteListener) {
    super(context,R.layout.custom_list_row ,productNames);
    this.deleteListener = deleteListener;
}
 final Product singleProduct=getItem(position);
    final TextView productName=(TextView)customView.findViewById(R.id.ProductName);
    final Button CheckButton = (Button)customView.findViewById(R.id.CheckButton);
    final Button DeleteButton = (Button)customView.findViewById(R.id.DeleteButton);
 DeleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               String product=singleProduct.get_productname();
                deleteListener.delete(product);
            }
        });

我的主要:

DbItemDeleteListener deleteListener;
ArrayAdapter<Product> adapter;
ArrayList<Product> productnames=new ArrayList<>();
DBHandler dbhandler;
 @Override
public void delete(String productId){
    dbhandler.deleteProduct(productId);
}

还有我的 DBHandler:

  public void deleteProduct(String productname){
    SQLiteDatabase db=getWritableDatabase();
    db.execSQL("DELETE FROM " +TABLE_PRODUCTS+ " WHERE "+ COLUMN_PRODUCTNAME+ "=\" "+ productname +"\";");
    }

当我单击删除按钮时,我也在 logcat 中收到此消息:

 Process: com.example.olev.shoppinglist, PID: 1836
    java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.olev.shoppinglist.DbItemDeleteListener.delete(java.lang.String)' on a null object reference
            at com.example.olev.shoppinglist.CustomAdapter$3.onClick(CustomAdapter.java:80)
            at android.view.View.performClick(View.java:4756)

【问题讨论】:

  • 为什么不直接点击listview按钮删除?
  • 因为按钮是使用 CustomAdapter 创建的。

标签: android sqlite listview android-intent


【解决方案1】:

您不应该真的只需要使用意图来删除列表项。相反,使用观察者模式。首先,创建一个接口:

public interface DbItemDeleteListener{
    public void delete(String productId);
}

在您的 Activity 中实现接口(您的 Activity 可能不是最好的实现位置,但因为它是您已经在执行删除操作的地方,所以我会坚持这样做):

public class MyActivity extends Activity implements DbItemDeleteListener{

    ...

    @Override
    public void delete(String productId){
        dbhandler.deleteProduct(productId);
    }
}

然后,将实现侦听器的类的实例传递给适配器的构造函数:

public CustomAdapter extends WhateverAdapter{
    private DbItemDeleteListener deleteListener;

    public MyAdapter(DbItemDeleteListener deleteListener){
        this.deleteListener = listener;
    }
}

确保在创建适配器时使用此版本的构造函数。

然后,而不是 onClickListener 发送一个意图:

DeleteButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //get the product name and use the listener to delete

        ...

        deleteListener.delete(productId);
        notifyDataSetChanged();            
    }
}

但如果你出于某种原因仍打算使用 Intent:

http://developer.android.com/reference/android/app/Activity.html#onNewIntent(android.content.Intent)

如果活动在其包中将 launchMode 设置为“singleTop”,或者客户端在调用 startActivity(Intent) 时使用了 FLAG_ACTIVITY_SINGLE_TOP 标志,则会调用此方法。

我猜正在发生的是,您实际上是在创建一个新实例,而不是获取 Main 活动的当前实例。因此,您应该改为在 onCreate() 中进行相同的检查。

因此,您可以将 Activity 的启动模式设置为调用 onNewIntent 的方式:

<activity
    android:launchMode="singleTop"
    ...>
    ....
</activity>

和/或将标志添加到您的意图中:

intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

或者,也许更简单,您可以将删除调用移至 onCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {

    ... //other onCreate() stuff

    if(getIntent() != null && getIntent().hasExtra("deleteProduct")){
        if (intent.getStringExtra("deleteProduct").equals("deleteProduct")) {
            deleteProduct();
        }
    }
}

另外,你应该检查一下

intent.getStringExtra("deleteProduct").equals("deleteProduct")

不是您的示例代码中的 ".equals("deleteProcust"),但我认为这是一个错字。

【讨论】:

  • 那么有更简单的方法吗??
  • 我用一个建议更新了我的答案。如果还有什么不清楚的地方请告诉我。
  • 我认为您在创建适配器时可能仍在使用旧的构造函数 ("myAdapter = new CustomAdapter(context, productNames)" 而不是 "myAdapter = new CustomAdapter(context, productNames, this)" ),尽管我没有看到您执行此操作的任何代码。我看到我在回答中没有提到这一点,所以我会添加它。
  • 完美! 2 处更改:在 getProductsFromDb() 中,将其作为第一行插入:“productnames.clear();”。此外,在 DB 处理程序的 deleteProduct() 中,而不是 execSql,您应该像这样使用 delete:“public void deleteProduct(String productname){ SQLiteDatabase db=getWritableDatabase(); String[] args = {productname}; db.删除(TABLE_PRODUCTS, COLUMN_PRODUCTNAME+"= ?", args); }"
  • 当然。只需在活动的 delete() 方法中构建对话框,并在用户确认后才调用 dbhandler.deleteProduct() 和 getProductsFromDB()。
猜你喜欢
  • 1970-01-01
  • 2016-06-01
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多