Firebase首次登录后导航头部未显示用户displayName问题
看起来你遇到的问题是首次设置displayName后,MainActivity的导航抽屉无法即时获取到最新的用户名,但其他Activity却能正常显示,这大概率是Firebase Auth本地缓存同步延迟导致的,和旧版本SDK的bug关系不大,下面给你几个可行的解决方案:
方案1:确保displayName更新完成后再跳转MainActivity
你在欢迎页面设置用户名的时候,应该是调用了updateProfile方法,但如果在更新完成前就跳转到MainActivity,本地的currentUser对象还是旧的缓存值(displayName为null)。所以要在updateProfile的回调里完成跳转:
// 欢迎页面设置用户名的代码 EditText usernameInput = findViewById(R.id.username_input); FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); if (currentUser != null) { UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder() .setDisplayName(usernameInput.getText().toString().trim()) .build(); currentUser.updateProfile(profileUpdates) .addOnCompleteListener(task -> { if (task.isSuccessful()) { // 确认用户名更新成功后,再跳转到MainActivity Intent toMain = new Intent(WelcomeActivity.this, MainActivity.class); startActivity(toMain); finish(); // 关闭欢迎页,避免返回 } }); }
这样MainActivity启动时,currentUser的displayName已经是最新的了。
方案2:在MainActivity中主动刷新用户信息
如果跳转逻辑无法修改,可以在MainActivity里主动调用reload()方法刷新用户信息,从服务器拉取最新的profile:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ... 你的其他初始化代码(DrawerLayout、NavigationView等) FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); if (user != null) { // 刷新用户信息,确保拿到最新的displayName user.reload().addOnCompleteListener(task -> { if (task.isSuccessful()) { String userName = user.getDisplayName(); View header = navigationView.getHeaderView(0); TextView text = header.findViewById(R.id.username); text.setText(userName); } }); } }
reload()会异步从服务器获取最新的用户数据,回调里更新UI就能拿到正确的用户名了。
方案3:监听Auth状态变化,自动更新UI
更可靠的方式是注册AuthStateListener,监听用户登录状态或profile的变化,一旦有更新就自动刷新导航抽屉的用户名:
private FirebaseAuth.AuthStateListener authStateListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // ... 初始化Drawer、NavigationView等 // 创建Auth状态监听器 authStateListener = firebaseAuth -> { FirebaseUser user = firebaseAuth.getCurrentUser(); if (user != null) { // 用户状态变化(包括profile更新)时,更新导航抽屉用户名 String userName = user.getDisplayName(); View header = navigationView.getHeaderView(0); TextView text = header.findViewById(R.id.username); text.setText(userName); } }; } @Override protected void onStart() { super.onStart(); // 启动时添加监听器 FirebaseAuth.getInstance().addAuthStateListener(authStateListener); } @Override protected void onStop() { super.onStop(); // 停止时移除监听器,避免内存泄漏 if (authStateListener != null) { FirebaseAuth.getInstance().removeAuthStateListener(authStateListener); } }
这个方案能覆盖所有用户信息更新的场景,不仅是首次设置用户名,后续如果修改了profile,导航抽屉也会自动更新。
为什么另一个Activity能正常显示?
这是因为另一个Activity启动的时机较晚,Firebase Auth已经完成了本地缓存和服务器数据的同步,所以能拿到最新的displayName;而MainActivity是在设置用户名后立即跳转的,此时缓存还没来得及更新,所以取到的是旧值。
内容的提问来源于stack exchange,提问作者Kaiser

