Kotlin中Firebase数据库用户详情获取及页面崩溃问题求助
问题分析与解决方案
核心问题总结
- 初始化顺序错误:调用
loadUserDetails()时,Firebase相关实例和UID还未初始化,触发空指针异常 - 重复跳转当前页面:点击个人资料导航按钮时重复启动
User_Activity,引发栈异常 - 数据读取逻辑错误:错误遍历用户节点的子字段,无法正确获取用户数据
- 未处理未登录状态:未校验用户登录状态,无权限访问数据时触发异常跳转
分步修复方案
1. 调整初始化顺序
将loadUserDetails()移到Firebase实例、UID、数据库引用初始化完成之后,同时校验用户登录状态,未登录直接跳转登录页:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityUserBinding.inflate(layoutInflater) setContentView(binding.root) // 先初始化Firebase并校验登录状态 firebaseAuth = FirebaseAuth.getInstance() val currentUser = firebaseAuth.currentUser if (currentUser == null) { startActivity(Intent(this, MainActivity::class.java)) finish() return } uid = currentUser.uid databaseReference = FirebaseDatabase.getInstance().getReference("Users") // 再加载用户数据 loadUserDetails() // 其他按钮逻辑... }
2. 修复导航栏跳转逻辑
点击个人资料按钮时,无需重复启动当前Activity,直接提示或忽略:
val gotoUser: ImageView = findViewById(R.id.navUser) gotoUser.setOnClickListener { Toast.makeText(this, "已在个人资料页", Toast.LENGTH_SHORT).show() }
3. 修正Firebase数据读取逻辑
根据你的数据库结构,Users节点下直接以用户UID为子节点,每个子节点包含email、username、id字段,无需遍历子节点,直接从快照读取:
private fun loadUserDetails() { val userRef = databaseReference.child(uid) userRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { // 直接从用户节点快照读取字段,添加空值默认处理 val email = snapshot.child("email").value?.toString() ?: "未知邮箱" val username = snapshot.child("username").value?.toString() ?: "未知用户名" val userId = snapshot.child("id").value?.toString() ?: "未知ID" binding.profileUID.text = userId binding.profileEmail.text = email binding.profileUsername.text = username } override fun onCancelled(error: DatabaseError) { Log.e("FirebaseError", "数据读取失败: ${error.message}") } }) }
4. 优化登出逻辑
调用Firebase登出方法并清除Activity栈,避免用户返回个人资料页:
val LogoutBtn = findViewById<Button>(R.id.logoutBtn) LogoutBtn.setOnClickListener { firebaseAuth.signOut() val intent = Intent(this@User_Activity, MainActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) finish() }
完整修改后的代码
class User_Activity : AppCompatActivity() { private lateinit var binding: ActivityUserBinding private lateinit var databaseReference: DatabaseReference private lateinit var firebaseAuth: FirebaseAuth private lateinit var uid: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityUserBinding.inflate(layoutInflater) setContentView(binding.root) // 初始化FireAuth并校验登录状态 firebaseAuth = FirebaseAuth.getInstance() val currentUser = firebaseAuth.currentUser if (currentUser == null) { startActivity(Intent(this, MainActivity::class.java)) finish() return } uid = currentUser.uid databaseReference = FirebaseDatabase.getInstance().getReference("Users") // 加载用户数据 loadUserDetails() // 登出按钮逻辑 val LogoutBtn = findViewById<Button>(R.id.logoutBtn) LogoutBtn.setOnClickListener { firebaseAuth.signOut() val intent = Intent(this@User_Activity, MainActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) finish() } // 导航栏跳转逻辑 val addImg: ImageView = findViewById(R.id.navCreate) addImg.setOnClickListener { startActivity(Intent(this@User_Activity, Slam_Activity::class.java)) } val gotoUser: ImageView = findViewById(R.id.navUser) gotoUser.setOnClickListener { Toast.makeText(this, "已在个人资料页", Toast.LENGTH_SHORT).show() } val gotoHome: ImageView = findViewById(R.id.navHome) gotoHome.setOnClickListener { startActivity(Intent(this@User_Activity, Homepage_Activity::class.java)) } } private fun loadUserDetails() { val userRef = databaseReference.child(uid) userRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val email = snapshot.child("email").value?.toString() ?: "未知邮箱" val username = snapshot.child("username").value?.toString() ?: "未知用户名" val userId = snapshot.child("id").value?.toString() ?: "未知ID" binding.profileUID.text = userId binding.profileEmail.text = email binding.profileUsername.text = username } override fun onCancelled(error: DatabaseError) { Log.e("FirebaseError", "数据读取失败: ${error.message}") } }) } }
内容的提问来源于stack exchange,提问作者John Villamor
相关产品推荐
相关产品推荐

