我正在尝试在我的项目中设置一个配置文件页面,并且我正在尝试实现一个功能,当用户单击底部的配置文件选项卡时,它将显示重定向到配置文件后存储在我的项目数据库中的信息页。
这是我的个人资料页面的代码:
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)
loadUserDetails()
firebaseAuth = FirebaseAuth.getInstance()
uid = firebaseAuth.currentUser?.uid.toString()
databaseReference = FirebaseDatabase.getInstance().getReference("Users")
val LogoutBtn = findViewById<Button>(R.id.logoutBtn)
LogoutBtn.setOnClickListener {
val intent = Intent(this@User_Activity, MainActivity::class.java)
startActivity(intent)
}
//navbar redirection
val addImg: ImageView = findViewById(R.id.navCreate)
addImg.setOnClickListener {
val intent = Intent(this@User_Activity, Slam_Activity::class.java)
startActivity(intent)
}
val gotoUser: ImageView = findViewById(R.id.navUser)
gotoUser.setOnClickListener {
val intent = Intent(this@User_Activity, User_Activity::class.java)
startActivity(intent)
}
val gotoHome: ImageView = findViewById(R.id.navHome)
gotoHome.setOnClickListener {
val intent = Intent(this@User_Activity, Homepage_Activity::class.java)
startActivity(intent)
}
}
这是我正在尝试实现的功能:
private fun loadUserDetails() {
//db ref to fetch user info
val userRef = databaseReference.child(uid)
userRef
.addValueEventListener(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
for (usersnapshot in snapshot.children) {
//Log.d("FirebaseData", "Snapshot: $snapshot")
val email = usersnapshot.child("email").value.toString()
val username = usersnapshot.child("username").value.toString()
val uid = usersnapshot.child("id").value.toString()
//Log.d("FirebaseData", "Email: $email, Username: $username, UID: $uid")
binding.profileUID.text = uid
binding.profileEmail.text = email
binding.profileUsername.text = username
}
}
override fun onCancelled(error: DatabaseError) {
Log.e("FirebaseError", "Error: $error")
}
})
}
这就是我的数据库的样子:
单击导航栏上的个人资料选项卡后,现在发生的情况是它循环回到登录页面,当您再次单击个人资料选项卡时,它会崩溃。
我尝试过编写不同的代码,但即使在研究了大量文章之后,我仍然一无所获。输出应该返回当前用户 ID 的所有数据。
你能试试这个吗:
private fun loadUserDetails() {
// Check if user is logged in
val currentUser = firebaseAuth.currentUser
if (currentUser == null) {
// Redirect to login activity or handle unauthenticated user
return
}
val userRef = databaseReference.child(currentUser.uid)
userRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()) {
val email = snapshot.child("email").value.toString()
val username = snapshot.child("username").value.toString()
val uid = snapshot.child("id").value.toString()
binding.profileUID.text = uid
binding.profileEmail.text = email
binding.profileUsername.text = username
} else {
// Handle case where user data does not exist
}
}
override fun onCancelled(error: DatabaseError) {
Log.e("FirebaseError", "Error: $error")
// Handle database error
}
})
}
我刚刚添加了一个检查用户是否已登录的检查。 然后我使用
addListenerForSingleValueEvent
而不是 addValueEventListener
来获取一次数据,而不是监听所有数据更改。
您正在从
/Users/$userId
加载数据,因此您在 DataSnapshot
中获得的 onDataChange
将包含单个用户的信息。
但是
onDataChange
中的代码会循环遍历数据快照的子节点,就好像它获取了结果列表一样。那是行不通的,这可能解释了崩溃的原因。
解决方案是从
onDataChange
实现中删除循环。仅当您获取结果列表时才需要这样的循环,而不是当您直接获取单个用户节点的快照时。
第二个问题是您使用的 UID 值:
val userRef = databaseReference.child(uid)
您将其初始化为:
uid
但是如果我们查看数据库的屏幕截图,其中的
uid = firebaseAuth.currentUser?.uid.toString()
值确实
不是似乎是由 Firebase 身份验证生成的 UID 值,而是通过调用 的
-Nl0...
方法生成的推送 ID实时数据库。因此,虽然您没有共享写入用户信息的代码,但似乎是这样的:
push()
如果你想使用 UID 来标识用户的节点,你不应该调用
databaseReference.push().setValue(...);
,而是执行类似于
push()
中所做的操作来构建:loadUserDetails
或
databaseReference.child(uid).setValue(...);