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
相关产品推荐
相关产品推荐

