Android中Firebase数据库按钮点击读取数据失败排查
Firebase Realtime Database 数据读取失败问题分析
问题背景
Firebase数据库结构如下:
{ "User": { "mail@gmail::com": { "-NKTbcSqxmB4XImNrpDq": { "Q": 0, "W": 0, "QW": 0, "WQ": 0 } }, "mail@gmail:com": { "-NKTbcTUBxMsXYopKMO-": { "Q1": 0, "W1": 0, "QW1": 0, "WQ1": 0 } } } }
点击按钮时尝试读取两个用户数据并存入SharedPreferences,但读取失败且无异常输出,原按钮监听代码如下:
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { database.child("User").child(getMail1).get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() { @Override public void onComplete(@NonNull Task<DataSnapshot> task) { if (task.isSuccessful()) { User value = dataSnapshot.child("User").child(getEmail1).getValue(User.class); PreferenceConfig.Q1(getApplicationContext(), Q1); PreferenceConfig.W1(getApplicationContext(), W1); PreferenceConfig.QW1(getApplicationContext(), QW1); PreferenceConfig.WQ1(getApplicationContext(), WQ1); } }); database.child("User").child(getMail1).get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() { @Override public void onComplete(@NonNull Task<DataSnapshot> task) { if (task.isSuccessful()) { User value = dataSnapshot.child("User").child(getEmail).getValue(User.class); PreferenceConfig.Q(getApplicationContext(), Q); PreferenceConfig.W(getApplicationContext(), W); PreferenceConfig.QW(getApplicationContext(), QW); PreferenceConfig.WQ(getApplicationContext(), WQ); } }); });
核心错误点
- 未从Task中获取DataSnapshot实例:原代码直接使用
dataSnapshot变量,但该变量未通过task.getResult()获取,属于未定义变量,实际运行时会引发错误 - 节点路径重复定位:第一个请求已经通过
database.child("User").child(getMail1)定位到用户节点,后续无需再通过dataSnapshot.child("User").child(getEmail1)重复查找,路径层级错误 - 第二个请求节点路径错误:第二个请求错误使用
getMail1作为子节点,应该使用getEmail - 数据解析层级错误:用户节点下还有一层随机生成的key(如
-NKTbcSqxmB4XImNrpDq),直接用User.class解析会失败,需要先获取该子节点的数据 - 未从解析对象中取值:保存SharedPreferences时直接使用
Q1、W1等未定义变量,未从解析后的对象中提取对应字段值
修正后的代码
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 读取第一个用户数据 database.child("User").child(getEmail1).get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() { @Override public void onComplete(@NonNull Task<DataSnapshot> task) { if (task.isSuccessful()) { DataSnapshot dataSnapshot = task.getResult(); // 遍历随机key子节点 for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) { User user = childSnapshot.getValue(User.class); if (user != null) { // 保存到SharedPreferences PreferenceConfig.Q(getApplicationContext(), user.getQ()); PreferenceConfig.W(getApplicationContext(), user.getW()); PreferenceConfig.QW(getApplicationContext(), user.getQW()); PreferenceConfig.WQ(getApplicationContext(), user.getWQ()); } } } else { Log.e("TaskError", "读取第一个用户失败: " + task.getException()); } } }); // 读取第二个用户数据 database.child("User").child(getEmail).get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() { @Override public void onComplete(@NonNull Task<DataSnapshot> task) { if (task.isSuccessful()) { DataSnapshot dataSnapshot = task.getResult(); // 遍历随机key子节点 for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) { User1 user1 = childSnapshot.getValue(User1.class); if (user1 != null) { // 保存到SharedPreferences PreferenceConfig.Q1(getApplicationContext(), user1.getQ1()); PreferenceConfig.W1(getApplicationContext(), user1.getW1()); PreferenceConfig.QW1(getApplicationContext(), user1.getQW1()); PreferenceConfig.WQ1(getApplicationContext(), user1.getWQ1()); } } } else { Log.e("TaskError", "读取第二个用户失败: " + task.getException()); } } }); } });
配套实体类说明
需要对应两个用户的数据结构创建实体类:
// 对应mail@gmail::com节点下的数据结构 public class User { private int Q; private int W; private int QW; private int WQ; // Firebase解析必须的无参构造函数 public User() {} // getter方法 public int getQ() { return Q; } public int getW() { return W; } public int getQW() { return QW; } public int getWQ() { return WQ; } } // 对应mail@gmail:com节点下的数据结构 public class User1 { private int Q1; private int W1; private int QW1; private int WQ1; // Firebase解析必须的无参构造函数 public User1() {} // getter方法 public int getQ1() { return Q1; } public int getW1() { return W1; } public int getQW1() { return QW1; } public int getWQ1() { return WQ1; } }
额外说明
- Firebase Realtime Database实体类必须包含无参构造函数,否则Gson无法完成解析
- 如果随机key是唯一的,也可以通过
dataSnapshot.getChildren().iterator().next()直接获取第一个子节点,无需遍历 - 建议添加失败回调的日志输出,方便排查问题
内容的提问来源于stack exchange,提问作者user20704132
相关产品推荐
相关产品推荐

