Android点击按钮同步记录销售与更新库存时应用崩溃问题排查
诊断与修复你的销售管理功能崩溃问题
看起来你的UpdatadeStockAfterSells方法导致应用崩溃,我帮你梳理几个最可能的原因和对应的修复方案:
一、最可能的崩溃原因:类型转换异常与空值未处理
你的代码中直接把字符串转成Double,但没有处理空值或非数字格式的情况,这会直接抛出NumberFormatException导致崩溃;另外从UploadStockModel取值时也可能遇到null,进一步触发崩溃。
二、分步修复方案
1. 新增安全类型转换工具方法
先写一个工具方法,避免非法字符串转数字的崩溃:
private double safeParseDouble(String value) { if (value == null || value.trim().isEmpty()) { return 0.0; } try { return Double.parseDouble(value); } catch (NumberFormatException e) { Log.e("StockUpdate", "无效的数字格式: " + value, e); return 0.0; } }
2. 修复库存更新方法
修改UpdatadeStockAfterSells,加入空值校验、负数库存拦截,同时合并Firebase更新请求减少网络开销:
public void UpdatadeStockAfterSells(String ChildKey, String quantity_sold, String stock_Remaining_Quantity, String Stock_Quantity) { // 安全转换数字,避免崩溃 double remaining = safeParseDouble(stock_Remaining_Quantity); double sold = safeParseDouble(quantity_sold); double totalStock = safeParseDouble(Stock_Quantity); // 边界校验:避免除以0和库存负数 if (totalStock <= 0) { showToast("库存总量不能为0"); return; } double NewRemainingStock = remaining - sold; if (NewRemainingStock < 0) { showToast("销售数量超过剩余库存"); return; } double NewRemainingStockPercentage = (NewRemainingStock / totalStock) * 100; // 批量更新节点,减少网络请求 Map<String, Object> updates = new HashMap<>(); updates.put("percentageRemain", String.valueOf(NewRemainingStockPercentage)); updates.put("remainingQuantity", String.valueOf(NewRemainingStock)); mDatabaseReference.child(ChildKey).updateChildren(updates, new DatabaseReference.CompletionListener() { @Override public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { if (databaseError != null) { showToast("库存更新失败: " + databaseError.getMessage()); Log.e("StockUpdate", "更新库存出错", databaseError.toException()); } else { showToast("库存更新成功"); } } }); }
3. 处理上下文为空的情况
添加一个安全的Toast工具方法,避免Fragment/Activity销毁后调用Toast崩溃:
private void showToast(String message) { Context context = getContext(); if (context != null && !((Activity) context).isFinishing()) { Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } }
之后把所有Toast.makeText替换成showToast("xxx")即可。
4. 优化销售记录方法的异常捕获
在RecoredSales里加入数据存在性校验和异常捕获,避免单个商品处理失败导致整个流程崩溃:
public void RecoredSales() { final String spiner_seleceted_name = areaSpinner.getSelectedItem().toString(); final String Selling_Quantity = quantity.getText().toString(); // 先校验销售数量是否合法 if (Selling_Quantity.trim().isEmpty()) { showToast("请输入销售数量"); return; } mDatabaseReference.orderByChild("productName").equalTo(spiner_seleceted_name).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (!dataSnapshot.exists()) { showToast("未找到对应商品的库存"); return; } try { for (DataSnapshot areaSnapshot : dataSnapshot.getChildren()) { UploadStockModel stockModel = areaSnapshot.getValue(UploadStockModel.class); if (stockModel == null) { showToast("库存数据解析失败"); continue; } String stockRemainingQuantity = stockModel.getRemainingQuantity(); String stockQuantity = stockModel.getQuantity(); String KeyDb = areaSnapshot.getKey(); SaveSalesData(spiner_seleceted_name, Selling_Quantity); UpdatadeStockAfterSells(KeyDb, Selling_Quantity, stockRemainingQuantity, stockQuantity); } } catch (Exception e) { Log.e("RecordSales", "处理销售记录出错", e); showToast("销售记录保存失败: " + e.getMessage()); } } @Override public void onCancelled(DatabaseError databaseError) { Log.e("RecordSales", "查询库存被取消", databaseError.toException()); showToast("查询库存失败: " + databaseError.getMessage()); } }); }
三、额外优化建议
- 检查
UploadStockModel的字段名和Firebase数据库字段完全匹配(大小写敏感),否则会出现字段取值为null的情况; - 考虑使用Firebase事务更新库存,避免多用户同时操作导致的数据不一致;
- 可以用Firebase批量写操作,保证销售记录保存和库存更新要么都成功,要么都失败。
内容的提问来源于stack exchange,提问作者F.joel




