Android开发用Firebase Realtime Database实现登录无Logcat报错问题求助
问题排查与修复方案
1. 布局XML问题(你猜测的点确实存在问题)
TextInputLayout的官方推荐子控件是TextInputEditText而非原生EditText,原生EditText可能导致getEditText()读取值异常、空指针,或者样式不匹配的问题,修改代码如下:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/loginName" android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:background="@drawable/bg_edit_text" app:boxStrokeWidth="0dp" app:boxStrokeWidthFocused="0dp" android:backgroundTint="@android:color/transparent" > <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:background="@drawable/bg_edit_text" android:inputType="text" /> </com.google.android.material.textfield.TextInputLayout>
密码对应的TextInputLayout也做同样修改,把子控件换成TextInputEditText。
2. Java代码逻辑错误
2.1 validatePassword方法低级错误
你在密码校验逻辑中,误将错误提示全部设置到了用户名控件loginName上,导致密码为空、密码错误的提示完全不会显示在密码栏,你自然看不到报错,修正代码:
private Boolean validatePassword() { String val = loginPw.getEditText().getText().toString(); if (val.isEmpty()) { // 这里原来写的是loginName,改成loginPw loginPw.setError("Field cannot be empty"); return false; } else { // 这里原来写的是loginName,改成loginPw loginPw.setError(null); loginPw.setErrorEnabled(false); return true; } }
2.2 登录判断的逻辑运算符错误
loginUser方法中你用了按位或|,应该用短路逻辑或||,避免多余的校验执行:
public void loginUser (View view) { // 把 | 改成 || if (!validateUsername() || !validatePassword()) { return; } else { isUser(); } }
2.3 数据库取值逻辑错误
你通过orderByChild("name")查询到的快照snapshot,它的子节点是数据库中Users节点下的用户唯一ID,不是用户名本身,直接调用snapshot.child(userEnteredUsername)根本拿不到用户数据,这是你登录无反应的核心原因,修正逻辑:
private void isUser() { String userEnteredUsername = loginName.getEditText().getText().toString().trim(); String userEnteredPassword = loginPw.getEditText().getText().toString().trim(); reference = FirebaseDatabase.getInstance().getReference("Users"); Query checkUser = reference.orderByChild("name").equalTo(userEnteredUsername); checkUser.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()){ loginName.setError(null); loginName.setErrorEnabled(false); // 遍历查询到的用户节点,取第一个匹配的用户 for (DataSnapshot userSnapshot : snapshot.getChildren()) { String passwordFromDb = userSnapshot.child("password").getValue(String.class); if (passwordFromDb.equals(userEnteredPassword)){ Intent intent = new Intent(getApplicationContext(), HomeActivity.class); startActivity(intent); // 匹配成功直接返回,避免继续遍历 return; } else { loginPw.setError("Wrong Password"); loginPw.requestFocus(); } } } else { loginName.setError("No such user exists"); loginName.requestFocus(); } } @Override public void onCancelled(@NonNull DatabaseError error) { // 空实现会吃掉所有数据库错误,至少加个日志打印 Log.e("LoginError", error.getMessage()); } }); }
额外安全提示
不要在Realtime Database中存储明文密码,Firebase官方提供了专门的Firebase Auth服务处理用户登录注册逻辑,安全性远高于自定义存储密码的方案,建议后续切换到官方Auth方案。
内容的提问来源于stack exchange,提问作者aikagra
相关产品推荐
相关产品推荐

