在数据快照中设置布尔值在设置为 true 后返回 null



这是我的代码:

public class ChatActivity extends AppCompatActivity {
private String titleString, userID, uploadID, imageURL, userOnlineString;
private Boolean userOnlineBoolean;
private int imageRotation;
private TextView titleCustomBar, lastSeenCustomBar;
private ImageView imageCustomBar;
private DatabaseReference mDatabaseRefUser;
private FirebaseAuth mAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
mAuth = FirebaseAuth.getInstance();
mDatabaseRefUser = FirebaseDatabase.getInstance().getReference("Users");
//Log.e("Lol", userOnlineString);
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);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ChatActivity.this, "some error", Toast.LENGTH_SHORT).show();
}
});

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);
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Glide.with(this).load(imageURL)
.into(imageCustomBar);
imageCustomBar.setRotation(imageRotation);
if(userOnlineBoolean){
userOnlineString = "Online";
}
lastSeenCustomBar.setText(userOnlineString);

}
@Override
protected void onStart() {
super.onStart();
if(mAuth.getCurrentUser() == null){
Intent mainActivityIntent = new Intent(this, MainActivity.class);
startActivity(mainActivityIntent);
finish();
}
else {
mDatabaseRefUser.child(mAuth.getCurrentUser().getUid()).child("Online").setValue(true);
}
}

}

在日志中,userOnlineBoolean返回 true。再往下看,在if-statementuserOnline布尔值为空,这是为什么呢?

我尝试了很多更改,但没有任何效果。为什么返回true后为空。

我已经尝试解决此问题数小时,但我没有找到问题或看到问题。如果您知道我的代码出了什么问题,请随时与您分享。

虽然我没有运行代码,但我怀疑问题是由匿名内部类引起的。

让我们看一下方法"onCreate"的执行:

你叫超级, 您进行了几次静态调用。 将事件侦听器添加到对象(这是匿名内部类,已创建此实例,但不执行方法( 然后分配一些值 再打几个电话。 然后你"if"在值上,该值仅在更改侦听器中更改。

此时,您的布尔值尚未设置。 所以会抛出一个空指针。

有多种方法可以解决此问题,但希望您了解根本原因。

我设法通过这样做解决了我的问题:

public void onDataChange(DataSnapshot dataSnapshot) {
userOnlineBoolean = dataSnapshot.getValue(Boolean.class);
if(userOnlineBoolean){
userOnlineString = "Online";
settextmethod();
}
private void settextmethod() {
lastSeenCustomBar.setText(userOnlineString);
}

但我仍然不明白为什么我以前的方式是错误的。

通常异步调用EventListener。您的if-子句可能在执行onDataChange回调之前被处理。

在下面找到解决您问题的建议。

首先,您应该重新考虑变量userOnlineBoolean本身。考虑变量在其生命周期中可能具有的状态始终是一个好主意。在这种情况下,您可以争辩说只有两种状态:用户在线或未在线。如果是这样,则应避免该变量未定义为 null。立即初始化变量,即在声明它时:

private boolean userOnlineBoolean = false;

如您所见,我使用了primitive boolean而不是包装类Boolean来确保它不能为 null。

现在,onCreate()方法中有很多代码。我不知道您的应用程序的上下文,但该方法可能只调用一次。但是,您希望 UI 的相关部分不仅更新一次,而且可能每次数据库更改时更新一次。因此,代码应该进入EventListener,或者更好的是进入一个单独的方法,该方法从EventListener中调用。

好吧,您可能希望从onCreate((方法中删除以下代码:

if(userOnlineBoolean){
userOnlineString = "Online";
}
lastSeenCustomBar.setText(userOnlineString);

并把它放入这样的新方法中。

private void updateUIOnDatabaseChange() {
userOnlineString = userOnlineBoolean ? "Online" : "";
lastSeenCustomBar.setText(userOnlineString);
}

请注意,我已经考虑过用户的状态从在线更改为不在线的情况。这就是为什么我用三元运算符(if-else的缩写形式(替换了if子句。

并更新您的onDataChange,以及

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
userOnlineBoolean = dataSnapshot.getValue(Boolean.class);
updateUIOnDatabaseChange();
Log.e("lol ", ""+userOnlineBoolean);
}

我认为这是一个更实用和合理的设计。让我知道这是否适合您。

最新更新