You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:36:44