You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动