Kotlin+Android Studio:Firebase存储用户信息时User对象输出异常
问题描述
尝试将uid、username和profileImageUrl保存到Firebase数据库时,除User对象外其他变量都能输出预期值,但User对象日志显示为letsbuildthatapp.com.User@41cb40,怀疑User对象逻辑存在问题。
保存用户至数据库的函数:
private fun saveUserToFirebaseDatabase(profileImageUrl: String) { val uid = FirebaseAuth.getInstance().uid ?: "" val ref = FirebaseDatabase.getInstance().getReference("/users/$uid") val user = User(uid, username_edittext_register.text.toString(), profileImageUrl) ref.setValue(user) .addOnSuccessListener { Log.d("RegisterActivity", "Finally we saved the user to Firebase Database") val intent = Intent(this,LatestMessagesActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } .addOnFailureListener{ Log.d("RegisterActivity", "Failed to set value to database: ${it.message}") } Log.d("saveUserToDatabase","Task completed? User: $user") }
User类:
class User(val uid: String,val username: String,val profileImageUrl: String) { constructor() : this("", "", "") }
完整代码:
package letsbuildthatapp.com import android.app.Activity import android.content.ContentValues.TAG import android.content.Intent import android.graphics.drawable.BitmapDrawable import android.net.Uri import android.os.Bundle import android.provider.MediaStore import android.util.Log import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.firebase.auth.FirebaseAuth import com.google.firebase.database.FirebaseDatabase import com.google.firebase.storage.FirebaseStorage import kotlinx.android.synthetic.main.activity_register.* import java.util.* class RegisterActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_register) register_button_register.setOnClickListener { performRegister() } already_have_account_text_view.setOnClickListener { Log.d("RegisterActivity", "Try to show login activity") //Launch the login activity somehow val intent = Intent(this, LoginActivity::class.java) startActivity(intent) } selectphoto_button_register.setOnClickListener { Log.d("RegisterActivity", "Try to show photo selector") val intent = Intent(Intent.ACTION_PICK) intent.type = "image/*" startActivityForResult(intent, 0) } } var selectedPhotoUri: Uri? = null override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 0 && resultCode == Activity.RESULT_OK && data != null) { Log.d("RegisterActivity", "Photo was selected") selectedPhotoUri = data.data val bitmap = MediaStore.Images.Media.getBitmap(contentResolver,selectedPhotoUri) select_photo_imageView_register.setImageBitmap(bitmap) selectphoto_button_register.alpha = 0f } } private fun performRegister() { val username = username_edittext_register.text.toString() val email = email_edittext_register.text.toString() val password = password_edittext_register.text.toString() if (email.isEmpty() || password.isEmpty()) { Toast.makeText(this,"Please enter text in email/password", Toast.LENGTH_SHORT).show() return } Log.d("RegisterActivity", "Username: $username") Log.d("RegisterActivity", "Email is: $email") Log.d("RegisterActivity", "Password: $password") // Firebase Authentication to create a user with email and password FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password) .addOnCompleteListener{ if (!it.isSuccessful) return@addOnCompleteListener //else if successful Log.d("RegisterActivity", "Successfully created user with uid: ${it.result.user!!.uid}") uploadImageToFirebaseStorage() } .addOnFailureListener{ Log.d("RegisterActivity","Failed to create user: ${it.message}") Toast.makeText(this,"Failed to create user: ${it.message}", Toast.LENGTH_SHORT).show() } } private fun uploadImageToFirebaseStorage() { if (selectedPhotoUri == null) return val filename = UUID.randomUUID().toString() val ref = FirebaseStorage.getInstance().getReference("/images/$filename") ref.putFile(selectedPhotoUri!!) .addOnSuccessListener { Log.d("RegisterActivity", "Successfully uploaded image: ${it.metadata?.path}") ref.downloadUrl.addOnSuccessListener { Log.d("RegisterActivity", "File Location: $it") saveUserToFirebaseDatabase(it.toString()) } } .addOnFailureListener{ Log.d("RegisterActivity", "Failed") Toast.makeText(this,"Failed: ${it.message}", Toast.LENGTH_SHORT).show() } } private fun saveUserToFirebaseDatabase(profileImageUrl: String) { val uid = FirebaseAuth.getInstance().uid ?: "" val ref = FirebaseDatabase.getInstance().getReference("/users/$uid") val user = User(uid, username_edittext_register.text.toString(), profileImageUrl) ref.setValue(user) .addOnSuccessListener { Log.d("RegisterActivity", "Finally we saved the user to Firebase Database") val intent = Intent(this,LatestMessagesActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } .addOnFailureListener{ Log.d("RegisterActivity", "Failed to set value to database: ${it.message}") } Log.d("saveUserToDatabase","Task completed? User: $user") } } class User(val uid: String,val username: String,val profileImageUrl: String) { constructor() : this("", "", "") }
问题分析与解决
问题根源
- 日志显示问题:直接打印User对象时,默认调用
Any类的toString()方法,输出格式为包名.类名@哈希值,仅代表对象内存标识,而非实际属性数据。 - Firebase序列化隐患:普通Kotlin类未满足Firebase Realtime Database的序列化要求,虽然有默认构造函数,但字段无法被自动识别序列化,可能导致数据库写入异常。
解决方案
1. 自定义toString()方法(解决日志显示)
修改User类,添加自定义toString()方法,让日志输出对象的实际属性值:
class User(val uid: String, val username: String, val profileImageUrl: String) { constructor() : this("", "", "") override fun toString(): String { return "User(uid='$uid', username='$username', profileImageUrl='$profileImageUrl')" } }
2. 改用Kotlin Data Class(推荐,双重解决问题)
Kotlin的Data Class会自动生成toString()、equals()等方法,同时Firebase能更友好地处理其序列化逻辑:
data class User(val uid: String, val username: String, val profileImageUrl: String) { constructor() : this("", "", "") }
修改后,打印User对象会直接输出所有属性值,同时Firebase能正确将字段写入数据库。
3. 验证结果
重新运行代码,查看日志中User对象的输出内容,同时登录Firebase控制台,检查/users/[uid]路径下是否存在uid、username、profileImageUrl三个字段的正确数据。
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

