【问题标题】:Updating the SQLite DB with a Button click on listView使用单击 listView 的按钮更新 SQLite DB
【发布时间】:2018-01-19 22:23:46
【问题描述】:

我正在尝试构建一个简单的股票应用程序,我的主要活动有一个列表视图,在我拥有的每个列表项上都有一个“出售”按钮。 Sell 按钮的功能应该通过更新该项目的行并将数量设置为数量-1 来减少该特定项目的数量。

为了实现这一点,我发现在我的自定义光标适配器类中设置点击监听器是一种方法。我正在为我的数据库操作使用内容提供程序类。所以我试图做的是,在我的光标适配器中的 OnClickListener 中触发我的主要活动中的一个函数。这是一些可以解释更多的代码。 (请原谅我糟糕的编程技巧,我是新手)

由于某种原因,我的方法似乎不起作用,第一次单击 Sell 按钮没有做任何事情,第二次单击使应用程序崩溃,原因是:

  android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method.

附言我没有从适配器发送上下文来减少计数方法,它导致 getContentResolver() 上的空指针崩溃。

我的内容提供程序中的更新功能:

private int updateItem (Uri uri, ContentValues values, String selection, String[] selectionArgs){

    if (values.containsKey(InventoryContract.ItemEntry.COLUMN_NAME)){
        String name = values.getAsString(InventoryContract.ItemEntry.COLUMN_NAME);
        if (name == null){
            throw new IllegalArgumentException("Item requires a name");
        }
    }

    // If values size is zero, do not try to update the database.
    if (values.size() == 0){
        return 0;
    }

    // Otherwise, get writeable database to update the data
    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    // Perform the update on the database and get the number of rows affected
    int rowsUpdated = database.update(InventoryContract.ItemEntry.TABLE_NAME, values, selection, selectionArgs);

    // If 1 or more rows were updated, then notify all listeners that the data at the
    // given URI has changed
    if (rowsUpdated != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

    // Return number of rows updated
    return rowsUpdated;
}

我在主要活动中编写(或尝试编写)的函数

    public void decreaseCount(Context context, int columnId, int quantity){

    quantity = quantity -1;

    ContentValues values = new ContentValues();
    values.put(InventoryContract.ItemEntry.COLUMN_QUANTITY, quantity);

    Uri updateUri = ContentUris.withAppendedId(InventoryContract.ItemEntry.CONTENT_URI, columnId);

    int rowsAffected = context.getContentResolver().update(updateUri, values,null, null);

}

最后,我添加到按钮的自定义 OnClickListener(p.s. 监听器位于光标适配器的覆盖 bindView 方法中)

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

            int columnIdIndex = mCursor.getColumnIndex(InventoryContract.ItemEntry._ID);
            int quantityIndex = mCursor.getColumnIndex(InventoryContract.ItemEntry.COLUMN_QUANTITY);

            CatalogActivity catalogActivity = new CatalogActivity();
            catalogActivity.decreaseCount(context2, Integer.valueOf(mCursor.getString(columnIdIndex)), Integer.valueOf(mCursor.getString(quantityIndex)));
        }
    });

提前谢谢你!

【问题讨论】:

  • 对不起,添加了更多细节,我不小心保存了。
  • github.com/tipialican/InventoryApp 这里是 repo,如果有人想查看它
  • 从日志中显示完整的堆栈跟踪,而不仅仅是一行。将管理 mCursor 的代码显示为 StaleDataException - 当 Cursor 包含陈旧数据并且必须在再次使用之前重新查询时引发此异常。
  • 嘿,迈克,事实证明我的代码实际上是在减少商品的数量,但出于某种原因,无论点击了销售按钮的商品,它都会这样做
  • 究竟为什么完整的堆栈跟踪很重要,它说明了什么是什么,特别是问题发生在哪里。

标签: android sqlite listview android-cursoradapter


【解决方案1】:

这个问题很简单。我修复了你的代码。首先不要从活动中创建对象。尝试使用装箱和拆箱技术来检索您的上下文。在您的InsertCursorAdapter 构造函数中应该是这样的

public ItemCursorAdapter(Context context, Cursor c) { super(context, c); this.context = context; }

那么你需要从bindView方法中保存你的cursor。

然后你需要绑定上下文对象来取回你的活动对象。总而言之,你会有这样的东西:

 @Override
public void bindView(View view, final Context context, Cursor cursor) {
    this.mCursor = cursor;
    TextView nameTextView = view.findViewById(R.id.name);
    TextView quantityTextView = view.findViewById(R.id.quantity);
     sellButton = view.findViewById(R.id.sell_button);
    ImageView imageView = view.findViewById(R.id.item_image);

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

            int columnIdIndex = mCursor.getColumnIndex(InventoryContract.ItemEntry._ID);
            int quantityIndex = mCursor.getColumnIndex(InventoryContract.ItemEntry.COLUMN_QUANTITY);
            String col= mCursor.getString(columnIdIndex);
            String quan= mCursor.getString(quantityIndex);
            CatalogActivity catalogActivity = (CatalogActivity) context;
            catalogActivity.decreaseCount( Integer.valueOf(col), Integer.valueOf(quan));
        }
    });

我还更改了您的 decreaseCount 参数。因为此方法在activity 类中,所以您无需在需要减小值的任何时候传递它。 getContentResolver() 方法是超类 AppCompatActivity 中的一个方法,因为它是公开的,所以你的 Activity 已经实现了它。

 //TODO: Decrease count by one
public void decreaseCount(int columnId, int quantity){

    quantity = quantity -1;

    ContentValues values = new ContentValues();
    values.put(InventoryContract.ItemEntry.COLUMN_QUANTITY, quantity);

    Uri updateUri = ContentUris.withAppendedId(InventoryContract.ItemEntry.CONTENT_URI, columnId);

    int rowsAffected = getContentResolver().update(updateUri, values,null, null);

}

【讨论】:

  • 非常感谢您的所有解释,修复了我的代码。我现在有一个问题,当我的列表中有多个项目时,单击其中一个项目会减少列表中另一个项目的数量。但我可以为此创建另一个问题。再次感谢您抽出宝贵的时间。
  • aaand 通过将光标位置存储在我的 bindView 中解决了这个问题。再次感谢您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多