Firebase Realtime Database String类型值转换错误 管理员登录失败
问题原因
- 核心错误点在
AccessAccount方法的反序列化逻辑:你没有区分普通用户和管理员的实体类,两类账号的数据库数据都被强制转换为Users类处理。 - 你的Firebase数据库中
Admins节点存储的字段结构,和Users类的字段不匹配(字段名不一致、字段类型不一致、缺失必要字段、存在额外未知字段都有可能),导致反序列化失败,或者反序列化出的对象属性为null,调用getPhone()/getPassword()时触发空指针异常。 - 额外逻辑缺陷:当前自动登录逻辑仅记录记住我的勾选状态,没有区分用户身份,管理员账号勾选记住我后下次启动会错误跳转至普通用户的主页面。
修复方案
方案1(快速修复):对齐管理员节点和Users类结构
检查Firebase控制台中Admins节点下的所有字段,确保和Users类的字段名、字段类型完全一致,无缺失、无多余字段。比如Users类中phone为字符串类型,数据库中管理员的phone字段就不能存为数字类型。
方案2(规范修复):单独创建管理员实体类
新建和Admins节点结构完全匹配的Admin实体类,登录时根据当前登录身份选择对应的类做反序列化:
private void AccessAccount(String phone, String pass) { final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference(); rootRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.child(parentDbName).child(phone).exists()) { if (parentDbName.equals("Admins")) { Admin adminData = snapshot.child(parentDbName).child(phone).getValue(Admin.class); // 加空指针防护,避免反序列化失败崩溃 if (adminData == null || adminData.getPhone() == null || adminData.getPassword() == null) { Toast.makeText(LoginActivity.this, "账号数据异常", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); return; } if (adminData.getPhone().equals(phone) && adminData.getPassword().equals(pass)) { Toast.makeText(LoginActivity.this, "Admin: " + adminData.getName() + "\n工作顺利", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); startActivity(new Intent(LoginActivity.this, AdminCategoryActivity.class)); finish(); } else { Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); } } else { Users userData = snapshot.child(parentDbName).child(phone).getValue(Users.class); if (userData == null || userData.getPhone() == null || userData.getPassword() == null) { Toast.makeText(LoginActivity.this, "账号数据异常", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); return; } // 原有普通用户校验逻辑 if (userData.getPhone().equals(phone) && userData.getPassword().equals(pass)) { Toast.makeText(LoginActivity.this, "欢迎回来 " + userData.getName(), Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); startActivity(new Intent(LoginActivity.this, MainActivity.class)); finish(); } else { Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); } } } else { Toast.makeText(LoginActivity.this, "该手机号不存在", Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); } } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(LoginActivity.this, "登录失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); loadingDialog.dismiss(); } }); }
额外优化建议
修改记住我的存储逻辑,新增用户身份标识字段,自动登录时根据存储的身份跳转对应页面,避免管理员账号跳错页面。同时给onCancelled方法加错误提示,方便排查网络/权限类问题。
内容的提问来源于stack exchange,提问作者ElY
相关产品推荐
相关产品推荐

