通过Java类向Firebase传数据并在Activity取值,setValue存对象崩溃求助
解决Firebase Database保存对象崩溃问题 + 上传/读取属性方案
我来帮你搞定Firebase保存对象崩溃的问题,顺便给你实现上传和跨Activity取属性的完整方案~
一、崩溃原因分析&核心修复
你之前手动创建子节点没问题,但用对象setValue崩溃,大概率是你的Java实体类不符合Firebase序列化的要求,常见坑点有这几个:
- 没有无参构造函数(Firebase需要用它来反序列化对象)
- 属性没有对应的getter方法(Firebase要读取属性值)
- 属性名和Firebase里的字段名不一致(大小写敏感!)
- 类不是public修饰的
正确的User实体类示例
按照Firebase要求写的实体类,直接复用就行:
public class User { // 必须保留无参构造函数,Firebase序列化必备 public User() {} // 带参构造,方便快速创建对象 public User(String name, String surname, String address, String tel, String dateOfBirth, String userName, String email) { this.name = name; this.surname = surname; this.address = address; this.tel = tel; this.dateOfBirth = dateOfBirth; this.userName = userName; this.email = email; } // 属性名要和你想存在Firebase里的字段完全一致(大小写别错) private String name; private String surname; private String address; private String tel; private String dateOfBirth; private String userName; private String email; // 每个属性都要有getter方法,Firebase需要读取这些值 public String getName() { return name; } public String getSurname() { return surname; } public String getAddress() { return address; } public String getTel() { return tel; } public String getDateOfBirth() { return dateOfBirth; } public String getUserName() { return userName; } public String getEmail() { return email; } }
二、RegCompleteActivity中保存对象的正确代码
把你的代码改成这样,确保Firebase引用初始化正确,对象创建和保存流程没问题:
public class RegComplete extends AppCompatActivity { private EditText Name, Surname, Address, Tel, DateOfBirth, Username; private FirebaseAuth mAuth; private DatabaseReference mDatabase; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_reg_complete); // 初始化Firebase Auth和数据库引用 mAuth = FirebaseAuth.getInstance(); mDatabase = FirebaseDatabase.getInstance().getReference(); // 绑定UI控件(记得替换成你的实际布局ID) Name = findViewById(R.id.et_name); Surname = findViewById(R.id.et_surname); Address = findViewById(R.id.et_address); Tel = findViewById(R.id.et_tel); DateOfBirth = findViewById(R.id.et_dob); Username = findViewById(R.id.et_username); } // 保存按钮的点击事件(布局里给按钮加android:onClick="saveUserInfo") public void saveUserInfo(View view) { // 获取输入框内容,记得trim()去掉首尾空格 String _name = Name.getText().toString().trim(); String _surname = Surname.getText().toString().trim(); String _address = Address.getText().toString().trim(); String _tel = Tel.getText().toString().trim(); String _dateOfBirth = DateOfBirth.getText().toString().trim(); String _userName = Username.getText().toString().trim(); // 获取当前登录用户的UID FirebaseUser currentUser = mAuth.getCurrentUser(); if (currentUser != null) { String uid = currentUser.getUid(); // 创建User对象 User user = new User(_name, _surname, _address, _tel, _dateOfBirth, _userName, currentUser.getEmail()); // 保存到users/uid路径下 mDatabase.child("users").child(uid).setValue(user) .addOnSuccessListener(unused -> Toast.makeText(RegComplete.this, "信息保存成功", Toast.LENGTH_SHORT).show()) .addOnFailureListener(e -> { Toast.makeText(RegComplete.this, "保存失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); // 打印异常到Logcat,方便排查深层问题 e.printStackTrace(); }); } else { Toast.makeText(this, "用户未登录,请先登录", Toast.LENGTH_SHORT).show(); } } }
三、在另一个Activity读取指定属性
比如在ProfileActivity里读取用户名,用addListenerForSingleValueEvent实现单次数据读取:
public class ProfileActivity extends AppCompatActivity { private TextView tvUserName; private FirebaseAuth mAuth; private DatabaseReference mDatabase; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); tvUserName = findViewById(R.id.tv_username); mAuth = FirebaseAuth.getInstance(); mDatabase = FirebaseDatabase.getInstance().getReference(); FirebaseUser currentUser = mAuth.getCurrentUser(); if (currentUser != null) { String uid = currentUser.getUid(); // 读取users/uid下的userName属性 mDatabase.child("users").child(uid).child("userName").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { String userName = snapshot.getValue(String.class); tvUserName.setText("当前用户名:" + userName); } else { tvUserName.setText("未设置用户名"); } } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(ProfileActivity.this, "读取失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); } } }
四、额外排查小技巧
- 查看Logcat的异常信息:如果是
NoSuchMethodException,就是缺无参构造;如果是NullPointerException,检查控件ID是否正确、用户是否登录 - 开发阶段可以暂时放开Firebase数据库规则(上线后一定要改回严格规则):
{ "rules": { ".read": true, ".write": true } }
内容的提问来源于stack exchange,提问作者Mobeen Kazmi
相关产品推荐
相关产品推荐

