You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于算术表达式向FireBase写入数据的实现问题

问题描述

我的Firebase数据库结构如下:
This is what my FireBase looks like
This is what my FireBase looks like

系统原本会提示用户将金币兑换为经验值,但我希望通过FireBase记录实现用户验证——用户必须提交兑换请求才能完成操作。写入FireBase时需满足以下要求:

  • 用户需指定要兑换的金币数量
  • 兑换后从用户账户余额中扣除对应数量的金币
  • 兑换的最低额度为5000金币

以下是我尝试实现写入FireBase的代码:

public void onClickResetCoin(View view) {
    mDatabase = FirebaseDatabase.getInstance().getReference("Resets");
    mDatabase.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            users.child(userID).child("coins").setValue(rescoin);
            int coins = Integer.parseInt(edCoins.getText().toString());
            int ResetCoin = rescoin - coins;
            String resetcoin = String.valueOf(ResetCoin);
            Reset newReset = new Reset(resetcoin);
            mDataBase.push().setValue(newReset);

        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}
解决方案

你的代码存在逻辑顺序错误、拼写问题以及缺少关键校验逻辑,下面给出修正后的完整实现:

1. 核心逻辑修正

  • 替换持续监听的addValueEventListener为一次性读取的addListenerForSingleValueEvent,避免不必要的重复触发
  • 先校验用户输入合法性与兑换条件,再执行数据库操作
  • 修正mDataBase拼写错误为mDatabase
  • 调整逻辑顺序:先读取当前金币余额,再计算扣除后的值并更新

2. 完整修正代码

public void onClickResetCoin(View view) {
    // 获取并校验用户输入
    String inputStr = edCoins.getText().toString().trim();
    if (inputStr.isEmpty()) {
        // 提示用户输入有效数值
        return;
    }

    int exchangeAmount;
    try {
        exchangeAmount = Integer.parseInt(inputStr);
    } catch (NumberFormatException e) {
        // 提示用户输入合法数字
        return;
    }

    // 校验最低兑换额度
    final int MIN_EXCHANGE = 5000;
    if (exchangeAmount < MIN_EXCHANGE) {
        // 提示用户最低需兑换5000金币
        return;
    }

    // 读取用户当前金币余额并执行兑换逻辑
    users.child(userID).child("coins").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            if (!snapshot.exists()) {
                // 用户金币数据不存在,提示错误
                return;
            }

            int currentCoins = snapshot.getValue(Integer.class);
            if (currentCoins < exchangeAmount) {
                // 用户金币不足,提示错误
                return;
            }

            // 更新用户金币余额
            users.child(userID).child("coins").setValue(currentCoins - exchangeAmount);

            // 记录兑换请求到Resets节点
            DatabaseReference resetsRef = FirebaseDatabase.getInstance().getReference("Resets");
            Reset newReset = new Reset(String.valueOf(exchangeAmount));
            resetsRef.push().setValue(newReset);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            // 处理数据库错误,比如提示用户操作失败
        }
    });
}

3. 并发安全优化建议

如果存在多端同时操作的场景,建议使用Firebase事务确保数据一致性,避免余额计算错误:

users.child(userID).child("coins").runTransaction(new Transaction.Handler() {
    @NonNull
    @Override
    public Transaction.Result doTransaction(@NonNull MutableData mutableData) {
        Integer currentCoins = mutableData.getValue(Integer.class);
        if (currentCoins == null || currentCoins < exchangeAmount) {
            return Transaction.abort();
        }
        mutableData.setValue(currentCoins - exchangeAmount);
        return Transaction.success(mutableData);
    }

    @Override
    public void onComplete(@Nullable DatabaseError error, boolean committed, @Nullable DataSnapshot currentData) {
        if (committed && error == null) {
            // 兑换成功后记录请求
            DatabaseReference resetsRef = FirebaseDatabase.getInstance().getReference("Resets");
            Reset newReset = new Reset(String.valueOf(exchangeAmount));
            resetsRef.push().setValue(newReset);
        } else {
            // 兑换失败,提示用户
        }
    }
});

内容的提问来源于stack exchange,提问作者ploxo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 00:11:04