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

Firebase DataSnapshot获取Boolean为true后,后续判断为何为null?

问题分析与解决方案

你的问题核心在于Firebase数据库操作的异步特性,这是新手使用Firebase时很容易踩的坑。

为什么会出现这个情况?

你在onCreate里调用了addValueEventListener来监听数据库中当前用户的Online字段,但Firebase的这个方法是异步执行的:

  • 当你调用addValueEventListener后,程序不会暂停等待onDataChange回调执行,而是直接继续向下执行后面的代码(比如获取Intent数据、设置ActionBar、执行if(userOnlineBoolean)判断)。
  • 等到数据库返回数据触发onDataChange时,if(userOnlineBoolean)的判断早就执行完了,这时候你打印的日志才会显示userOnlineBoolean为true,但这时候已经晚了。
  • 另外你声明userOnlineBoolean时没有初始化,默认值是null,所以第一次执行if(userOnlineBoolean)时,这个变量确实是null。

怎么解决?

把需要使用userOnlineBoolean的逻辑,移到onDataChange回调方法内部,确保只有当数据从数据库返回后,才去更新UI:

修改后的代码片段:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);
    mAuth = FirebaseAuth.getInstance();
    mDatabaseRefUser = FirebaseDatabase.getInstance().getReference("Users");

    Intent intent = getIntent();
    titleString = intent.getStringExtra("TITLE");
    userID = intent.getStringExtra("USERID");
    uploadID = intent.getStringExtra("UPLOADID");
    imageRotation = intent.getIntExtra("IMAGEROTATION", 0);
    imageURL = intent.getStringExtra("IMAGEURL");

    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayShowCustomEnabled(true);
    LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
    View customActionBar = layoutInflater.inflate(R.layout.chat_custombar, null);
    actionBar.setCustomView(customActionBar);

    titleCustomBar = findViewById(R.id.title_textview_id);
    lastSeenCustomBar = findViewById(R.id.last_seen_textview_id);
    imageCustomBar = findViewById(R.id.custom_image_id);

    titleCustomBar.setText(titleString);
    Glide.with(this).load(imageURL).into(imageCustomBar);
    imageCustomBar.setRotation(imageRotation);

    // 把监听逻辑放在UI初始化之后,并且将UI更新逻辑移到回调内
    mDatabaseRefUser.child(mAuth.getCurrentUser().getUid()).child("Online").addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            userOnlineBoolean = dataSnapshot.getValue(Boolean.class);
            Log.e("lol ", ""+userOnlineBoolean);
            // 在这里处理UI更新
            if(userOnlineBoolean != null && userOnlineBoolean){
                userOnlineString = "Online";
            } else {
                // 可以添加离线状态的处理,比如显示最后上线时间
                userOnlineString = "Offline";
            }
            lastSeenCustomBar.setText(userOnlineString);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Toast.makeText(ChatActivity.this, "some error", Toast.LENGTH_SHORT).show();
        }
    });
}

额外提示

另外我注意到你监听的是当前用户自己的Online状态,但在聊天界面里,通常应该监听的是聊天对象的在线状态?如果你是想显示对方的在线状态,那你应该把监听路径改成对方的userID,而不是当前用户的uid:

// 改成监听聊天对象的Online状态
mDatabaseRefUser.child(userID).child("Online").addValueEventListener(...)

这样就能正确获取对方的在线状态并更新UI了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:36:17