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

FireBase余额扣减操作执行不停歇?技术问题咨询

问题分析与解决方案

问题根源

你代码中使用的addValueEventListener是实时监听,只要users.child(userID).child("coins")的数据发生变化,onDataChange就会被触发。当你在onDataChange里执行updateChildren扣减积分后,coins的值更新,监听会再次触发并重复执行扣减逻辑,最终形成无限循环,导致积分被无终止重复扣除。


方案一:使用单次监听替代实时监听

将addValueEventListener替换为addListenerForSingleValueEvent,它只会读取一次数据,不会持续监听数据变化,从根源上避免循环触发:

Button btn_res = (Button) findViewById(R.id.btn_res);
btn_res.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        int coins = Integer.parseInt(edCoins.getText().toString());
        // 修正判断条件:与提示文本的"最少5000"保持一致
        if(coins < 5000){
            Toast.makeText(MainActivity2.this,"Минимум 5000", Toast.LENGTH_SHORT).show();
            return;
        } else {
            users.child(userID).child("coins").addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    ucoins = snapshot.getValue(Integer.class);
                    // 新增余额校验:确保用户余额足够扣减
                    if(ucoins >= coins){
                        HashMap hashMap = new HashMap();
                        hashMap.put("coins",ucoins - coins);
                        users.child(userID).updateChildren(hashMap).addOnSuccessListener(new OnSuccessListener() {
                            @Override
                            public void onSuccess(Object o) {
                                Toast.makeText(MainActivity2.this, "Заявка записана", Toast.LENGTH_SHORT).show();
                                // 把记录Reset的操作移到这里:确保扣减成功后再生成记录
                                Reset newReset = new Reset(coins);
                                mDataBase.push().setValue(newReset);
                            }
                        });
                    } else {
                        Toast.makeText(MainActivity2.this,"余额不足", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    // 处理取消事件,给用户反馈
                    Toast.makeText(MainActivity2.this,"操作失败", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
});

方案二:使用Firebase事务处理(更安全)

如果担心并发操作(比如用户多次快速点击按钮),推荐用事务处理,它能确保数据更新的原子性,避免并发导致的异常:

Button btn_res = (Button) findViewById(R.id.btn_res);
btn_res.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        int coins = Integer.parseInt(edCoins.getText().toString());
        if(coins < 5000){
            Toast.makeText(MainActivity2.this,"Минимум 5000", Toast.LENGTH_SHORT).show();
            return;
        }

        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 < coins){
                    return Transaction.abort();
                }
                mutableData.setValue(currentCoins - coins);
                return Transaction.success(mutableData);
            }

            @Override
            public void onComplete(@Nullable DatabaseError error, boolean committed, @Nullable DataSnapshot currentData) {
                if(committed){
                    Toast.makeText(MainActivity2.this, "Заявка записана", Toast.LENGTH_SHORT).show();
                    Reset newReset = new Reset(coins);
                    mDataBase.push().setValue(newReset);
                } else {
                    Toast.makeText(MainActivity2.this,"余额不足或操作失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
});

额外注意事项

  • 你原代码中判断条件coins < 1与提示文本"Минимум 5000"逻辑不一致,已修正为coins < 5000
  • 建议将记录Reset的操作移到扣减成功的回调内,避免出现"扣减失败但生成了Reset记录"的异常情况
  • 补充了onCancelled和事务失败的反馈逻辑,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 21:15:10