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

Firebase实时数据库数据触发页面刷新及跳转重复问题求助

问题修复与优化方案

修复后完整代码

public class TournamentFinal extends AppCompatActivity {
    TextView TeamRedScore, TeamBlueScore;
    private boolean hasGameEnded = false;
    private ValueEventListener scoreEventListener;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tournament_final);
        final DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);

        findViewById(R.id.imageMenu).setOnClickListener(view -> drawerLayout.openDrawer(GravityCompat.START));

        NavigationView navigationView = findViewById(R.id.navigationView);
        navigationView.setItemIconTintList(null);

        NavController navController = Navigation.findNavController(this, R.id.navHostFragment);
        NavigationUI.setupWithNavController(navigationView, navController);

        navigationView.setNavigationItemSelectedListener(menuItem -> {
            switch (menuItem.getItemId()) {
                case R.id.home:
                    startActivity(new Intent(TournamentFinal.this, MainActivity.class));
                    finish();
                    break;
                case R.id.setting:
                    startActivity(new Intent(TournamentFinal.this, SettingActivity.class));
                    break;
                case R.id.support:
                    startActivity(new Intent(TournamentFinal.this, SupportActivity.class));
                    break;
                case R.id.about_us:
                    startActivity(new Intent(TournamentFinal.this, InfoActivity.class));
                    break;
                case R.id.share:
                    startActivity(new Intent(TournamentFinal.this, ShareActivity.class));
                    break;
                case R.id.game:
                    startActivity(new Intent(TournamentFinal.this, TournamentFinal.class));
                    break;
            }
            return true;
        });

        BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
        bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
            switch (item.getItemId()){
                case R.id.home:
                    startActivity(new Intent(TournamentFinal.this, MainActivity.class));
                    finish();
                    break;
                case R.id.setting:
                    startActivity(new Intent(TournamentFinal.this, SettingActivity.class));
                    break;
                case R.id.game:
                    startActivity(new Intent(TournamentFinal.this, TournamentFinal.class));
                    break;
            }
            return false;
        });

        TeamRedScore = findViewById(R.id.team_red_score);
        TeamBlueScore = findViewById(R.id.team_blue_score);
        fetchdata();
    }

    public void fetchdata(){
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Team_score");
        scoreEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (hasGameEnded) return;

                String redScoreStr = snapshot.child("red_score").getValue(String.class);
                String blueScoreStr = snapshot.child("blue_score").getValue(String.class);

                if (redScoreStr != null) {
                    TeamRedScore.setText(redScoreStr);
                    int redScore = Integer.parseInt(redScoreStr);
                    if (redScore == 5) {
                        hasGameEnded = true;
                        reference.removeEventListener(this);
                        startActivity(new Intent(TournamentFinal.this, Red_win.class));
                        finish();
                    }
                }

                if (blueScoreStr != null) {
                    TeamBlueScore.setText(blueScoreStr);
                    int blueScore = Integer.parseInt(blueScoreStr);
                    if (blueScore == 5) {
                        hasGameEnded = true;
                        reference.removeEventListener(this);
                        startActivity(new Intent(TournamentFinal.this, Blue_win.class));
                        finish();
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                // 可添加错误提示逻辑
            }
        };
        reference.addValueEventListener(scoreEventListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (scoreEventListener != null) {
            FirebaseDatabase.getInstance().getReference().child("Team_score").removeEventListener(scoreEventListener);
        }
    }
}

关键修改说明

  • 移除定时刷新逻辑:Firebase的ValueEventListener本身会实时监听数据库变化,无需通过refresh()重复调用fetchdata(),原逻辑会重复添加监听器,导致多次触发跳转和性能浪费。
  • 新增游戏结束标记:用hasGameEnded变量标记游戏状态,一旦某队分数达标,后续数据变化不再处理跳转逻辑。
  • 简化数据读取逻辑:移除多余的子节点遍历,直接从Team_score节点下读取分数字段。
  • 跳转后清理资源:触发跳转时主动移除监听器,同时调用finish()结束当前页面,避免用户返回后再次触发跳转。
  • 内存泄漏防护:在onDestroy()中移除监听器,防止Activity销毁后监听器仍持有引用导致内存泄漏。

除按钮外的刷新方式

  • Firebase实时监听(推荐):使用ValueEventListener/ChildEventListener,数据库数据变化时自动回调,实时同步UI,适合实时性要求高的场景。
  • LiveData+ViewModel:将数据包装为LiveData,数据源变化时自动通知UI更新,配合ViewModel可避免配置变更(如屏幕旋转)导致的数据丢失,是Jetpack标准方案。
  • 广播接收器:发送自定义广播,在目标页面注册接收器,收到广播时执行刷新逻辑,适合跨页面/组件的通知刷新。
  • 内容观察者:针对ContentProvider数据源,注册ContentObserver监听数据变化,自动触发刷新。
  • WorkManager:适合低频率、非实时的刷新需求,即使App在后台也能执行任务,不会像Handler定时那样容易被系统杀死。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:05:16