如何通过条件获取Firebase子节点值并实现角色跳转登录
问题描述
用户希望实现登录页面功能:用户通过邮箱/密码登录后,根据其“role”字段值(分为Flood Victim、Rescuer、Admin)跳转到对应页面,其中Flood Victim对应HomeActivity.class,Rescuer对应HomeRes.class。当前无法正确从Firebase数据库获取用户的role字段值完成页面跳转,以下是相关代码及数据库结构截图。
原LoginActivity代码
mAuth.signInWithEmailAndPassword(userEmail, userPswd) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { //Sign in success, update UI with the signed-in user's information Toast.makeText(LoginActivity.this, "Login Successfull!",Toast.LENGTH_SHORT).show(); FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance(); DatabaseReference reference = firebaseDatabase.getReference().child("User"); //check if user has success registered reference.orderByChild("userName").equalTo(userEmail).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { Log.d("User exists", "Welcome!"); String value = snapshot.child("userRole").getValue().toString(); if (value.equals("Flood Victim") && value != null) { startActivity(new Intent(LoginActivity.this, HomeActivity.class)); finish(); } else if (value.equals("Rescuer")) { startActivity(new Intent(LoginActivity.this, homeRescuer.class)); finish(); } else { startActivity(new Intent(LoginActivity.this, homeFv.class)); finish(); } } } @Override public void onCancelled(@NonNull DatabaseError error) {} }); }else { // If sign in fails, display a message to the user. Toast.makeText(LoginActivity.this, "Error" + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); } } }); } } }
数据库结构截图

问题分析与修复方案
核心问题点
- 查询结果处理错误:
orderByChild("userName").equalTo(userEmail)返回的是包含匹配用户节点的快照,直接调用snapshot.child("userRole")无法正确获取字段值,需先遍历子节点或提取第一个匹配项。 - 空值判断顺序错误:先执行
value.equals("Flood Victim")再判断value != null,会触发空指针异常,应先判断值不为null再做比较。 - 字段名不匹配:数据库中角色字段为
role,但代码中使用userRole,导致无法获取正确值。 - 类名不一致:需求中Rescuer对应
HomeRes.class,但代码里写的是homeRescuer.class,需保持类名统一。
修复后的代码
mAuth.signInWithEmailAndPassword(userEmail, userPswd) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { Toast.makeText(LoginActivity.this, "登录成功!", Toast.LENGTH_SHORT).show(); FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance(); DatabaseReference reference = firebaseDatabase.getReference().child("User"); // 根据userName(邮箱)查询用户信息 reference.orderByChild("userName").equalTo(userEmail).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { Log.d("User exists", "Welcome!"); // 遍历查询到的用户节点(实际应只有一个匹配项) for (DataSnapshot userSnapshot : snapshot.getChildren()) { String role = userSnapshot.child("role").getValue(String.class); // 先判断role不为null再进行比较 if (role != null) { if (role.equals("Flood Victim")) { startActivity(new Intent(LoginActivity.this, HomeActivity.class)); } else if (role.equals("Rescuer")) { startActivity(new Intent(LoginActivity.this, HomeRes.class)); } else if (role.equals("Admin")) { // 补充Admin对应的页面跳转,示例为AdminHomeActivity startActivity(new Intent(LoginActivity.this, AdminHomeActivity.class)); } else { // 默认跳转页面 startActivity(new Intent(LoginActivity.this, homeFv.class)); } finish(); break; // 找到匹配用户后跳出循环 } } } else { Toast.makeText(LoginActivity.this, "未找到用户信息", Toast.LENGTH_SHORT).show(); } } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(LoginActivity.this, "数据库查询失败: " + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); } else { Toast.makeText(LoginActivity.this, "登录失败: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); } } });
额外优化建议
- 用Auth UID查询(更高效):如果数据库用户节点的键是Firebase Auth生成的用户UID,可直接通过
reference.child(mAuth.getCurrentUser().getUid())查询,无需orderByChild,性能更高。 - 添加异常处理:在获取字段值时增加异常捕获,避免因数据格式不一致导致崩溃。
- 统一类名规范:建议Activity类名采用大驼峰命名法(如
HomeRescuerActivity),避免小写开头的类名。
内容的提问来源于stack exchange,提问作者Mayya
相关产品推荐
相关产品推荐

