ListView项内Sell按钮点击更新SQLite数据库异常问题求助
解决库存应用Sell按钮的点击无响应与崩溃问题
你的问题主要来自两个关键错误,咱们一步步拆解修复:
核心问题分析
- 手动创建Activity实例完全无效:你在点击监听器里
new CatalogActivity(),但Android的Activity必须由系统初始化管理,手动new出来的实例没有完整的生命周期,getContentResolver()根本无法正常工作,这就是第一次点击没反应的原因。 - 点击时访问已失效的Cursor:当你点击按钮时,原有的Cursor可能已经因为数据更新(比如ContentProvider的
notifyChange)被关闭或替换,这时候再调用mCursor.getString()就会触发StaleDataException,导致第二次点击崩溃。
分步解决方案
1. 修复Activity实例获取方式,禁止手动new Activity
不要自己创建Activity实例,直接从按钮的上下文获取当前的CatalogActivity实例(因为Adapter是在Activity中初始化的,按钮的上下文就是Activity)。
2. 提前存储数据到按钮Tag,避免点击时访问Cursor
在bindView绑定数据的时候,就把当前商品的ID和数量存到按钮的Tag中,点击时直接从Tag取数据,彻底避开访问可能失效的Cursor:
修改后的bindView代码:
@Override public void bindView(View view, Context context, Cursor cursor) { // ... 其他绑定逻辑(比如商品名称、价格等) Button sellButton = view.findViewById(R.id.sell_button); // 从Cursor中获取当前项的ID和数量,此时Cursor是有效的 int itemId = cursor.getInt(cursor.getColumnIndex(InventoryContract.ItemEntry._ID)); int currentQuantity = cursor.getInt(cursor.getColumnIndex(InventoryContract.ItemEntry.COLUMN_QUANTITY)); // 用Pair存储这两个值,也可以自定义一个简单的ItemData类 Pair<Integer, Integer> itemInfo = new Pair<>(itemId, currentQuantity); sellButton.setTag(itemInfo); sellButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 从Tag中取出提前存储的数据 Pair<Integer, Integer> info = (Pair<Integer, Integer>) v.getTag(); int id = info.first; int quantity = info.second; // 获取正确的Activity实例 CatalogActivity activity = (CatalogActivity) v.getContext(); // 调用Activity的方法 activity.decreaseCount(id, quantity); } }); }
3. 优化Activity中的decreaseCount方法
既然方法就在Activity里,完全不需要传入Context,直接用自身的getContentResolver(),还可以加个数量判断避免负数:
public void decreaseCount(int columnId, int quantity){ // 防止数量变成负数 if (quantity <= 0) { Toast.makeText(this, "商品数量不能小于0", Toast.LENGTH_SHORT).show(); return; } int newQuantity = quantity - 1; ContentValues values = new ContentValues(); values.put(InventoryContract.ItemEntry.COLUMN_QUANTITY, newQuantity); Uri updateUri = ContentUris.withAppendedId(InventoryContract.ItemEntry.CONTENT_URI, columnId); getContentResolver().update(updateUri, values,null, null); }
4. 确保数据自动刷新
你的ContentProvider已经正确调用了getContext().getContentResolver().notifyChange(uri, null),所以如果主Activity使用了CursorLoader,它会自动监听数据变化并重新查询,ListView会自动更新显示最新数量。
为什么这样能解决问题?
- 不再手动创建Activity,用系统托管的实例调用方法,确保ContentResolver能正常执行数据库更新,第一次点击就能生效。
- 提前把数据存在按钮Tag里,点击时完全不依赖Cursor,避免了Cursor失效导致的崩溃问题。
内容的提问来源于stack exchange,提问作者paxcow
相关产品推荐
相关产品推荐

