进入注册Activity触发NullPointerException,需实现Firebase用户数据存储
注册页面打开即触发NullPointerException问题排查
问题概述
开发的Android应用进入Register Activity后立即崩溃,触发NullPointerException。该页面用于实现用户注册功能,计划将用户名、用户ID等信息存入Firebase实时数据库,但打开页面就崩溃。
错误日志
FATAL EXCEPTION: main Process: com.example.movies4u, PID: 18933 java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.firebase.auth.FirebaseAuth$AuthStateListener.onAuthStateChanged(com.google.firebase.auth.FirebaseAuth)' on a null object reference at com.google.firebase.auth.zzl.run(com.google.firebase:firebase-auth@@21.0.3:1) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:224) at android.app.ActivityThread.main(ActivityThread.java:7081) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:928)
注册页面代码
package com.example.movies4u; import static android.content.ContentValues.TAG; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.example.movies4u.Utils.FirebaseMethods; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.Task; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuthUserCollisionException; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; public class activity_register extends AppCompatActivity { TextView HaveAccount; EditText inputUsername,inputEmail,inputPassword,inputConfirmPassword; String username,email,password; Button btnRegister; FirebaseAuth mAuth; ProgressBar pb; private String userID; private FirebaseAuth.AuthStateListener mAuthListener; private FirebaseMethods firebaseMethods; private FirebaseDatabase mFirebaseDatabase; private DatabaseReference myRef; private String append; @SuppressLint("MissingInflatedId") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); //Hide status Bar setContentView(R.layout.activity_register); firebaseMethods =new FirebaseMethods(activity_register.this); HaveAccount= (TextView) findViewById(R.id.HaveAccount); pb = findViewById(R.id.progressBar3); inputUsername=findViewById(R.id.inputUsername); inputEmail=findViewById(R.id.inputEmail); inputPassword=findViewById(R.id.inputPassword); inputConfirmPassword=findViewById(R.id.inputConfirmPassword); btnRegister=findViewById(R.id.btnRegister); username=inputUsername.getText().toString(); email=inputEmail.getText().toString(); password=inputPassword.getText().toString(); pb.setVisibility(View.GONE); HaveAccount.setOnClickListener(view -> { Intent loginintent=new Intent(activity_register.this,login_activity.class); startActivity(loginintent); }); mAuth=FirebaseAuth.getInstance(); btnRegister.setOnClickListener(view -> ValidateDataandDoRegister()); } private void ValidateDataandDoRegister() { String username=inputUsername.getText().toString().trim(); String email=inputEmail.getText().toString().trim(); String password=inputPassword.getText().toString().trim(); String confirmPassword=inputConfirmPassword.getText().toString().trim(); if(email.isEmpty()){ inputEmail.setError("Enter Email Address"); inputEmail.requestFocus(); pb.setVisibility(View.GONE); } else if(email.length()<10){ inputEmail.setError("Enter valid Email"); inputEmail.requestFocus(); pb.setVisibility(View.GONE); } else if(password.isEmpty()){ inputPassword.setError("Enter the password"); inputPassword.requestFocus(); pb.setVisibility(View.GONE); } else if(password.length()<8){ inputPassword.setError("Password should be greater than 8 characters"); inputPassword.requestFocus(); pb.setVisibility(View.GONE); } else if(confirmPassword.isEmpty()){ inputConfirmPassword.setError("Re-Enter the Password"); inputConfirmPassword.requestFocus(); pb.setVisibility(View.GONE); } else if(confirmPassword.length()<8){ inputConfirmPassword.setError("Password should be greater than 8 characters"); inputConfirmPassword.requestFocus(); pb.setVisibility(View.GONE); } else if(!password.equals(confirmPassword)){ inputPassword.setError("Password not matched"); inputPassword.requestFocus(); inputConfirmPassword.setError("Password not matched"); inputConfirmPassword.requestFocus(); inputPassword.setText(""); inputConfirmPassword.setText(""); pb.setVisibility(View.GONE); } else{ pb.setVisibility(View.VISIBLE); doRegister(username,email,password); } } private void doRegister(String username,String email, String password) { pb.setVisibility(View.VISIBLE); mAuth.createUserWithEmailAndPassword(email, password).addOnSuccessListener(task -> { if(task != null ){ if(mAuth.getCurrentUser() != null){ userID=mAuth.getCurrentUser().getUid(); } // firebaseMethods.registerNewEmail(username,email,password); setupFirebaseAuth(); sendVerificationEmail(); // firebaseMethods.addNewUser(email, username); } }).addOnFailureListener(e -> { if(e instanceof FirebaseAuthUserCollisionException){ btnRegister.setEnabled(true); inputEmail.setError("Email Already Registered"); pb.setVisibility(View.GONE); inputEmail.requestFocus(); } else{ btnRegister.setEnabled(true); pb.setVisibility(View.GONE); Toast.makeText(activity_register.this, "Oops! Something Went wrong", Toast.LENGTH_SHORT).show(); } }); } private void sendVerificationEmail() { mAuth.getCurrentUser().sendEmailVerification().addOnCompleteListener(task -> { if(task != null && task.isSuccessful()){ btnRegister.setEnabled(true); pb.setVisibility(View.GONE); Toast.makeText(activity_register.this, "Email has been sent to your email address", Toast.LENGTH_SHORT).show(); //fixing the bug mAuth.signOut(); } else { btnRegister.setEnabled(true); pb.setVisibility(View.GONE); Toast.makeText(getApplicationContext(), "Oops! failed to send verification email",Toast.LENGTH_SHORT).show(); } }); } /* ------------------------------------ Firebase --------------------------------------------- */ /** * Setup the firebase auth object */ private void setupFirebaseAuth(){ Log.d(TAG, "setupFirebaseAuth: setting up firebase auth."); mAuth = FirebaseAuth.getInstance(); mFirebaseDatabase = FirebaseDatabase.getInstance(); myRef = mFirebaseDatabase.getReference(); //cannot get into this part of code mAuthListener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { FirebaseUser user=firebaseAuth.getCurrentUser(); if (user != null) { // User is signed in Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid()); myRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { //1st check: Make sure the username is not already in use if(firebaseMethods.checkIfUsernameExists(username, dataSnapshot)){ //to randomly generate key to make sure username is unique append = myRef.push().getKey().substring(3,10); Log.d(TAG, "onDataChange: username already exists. Appending random string to name: " + append); } username = username + append; //add new user to the database // firebaseMethods.addNewUser(email, username); Toast.makeText(activity_register.this, "SignUp successful", Toast.LENGTH_SHORT).show(); } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(activity_register.this, "unsuccessful", Toast.LENGTH_SHORT).show(); } }); finish(); } else { // User is signed out Toast.makeText(activity_register.this, "unsuccessful", Toast.LENGTH_SHORT).show(); Log.d(TAG, "onAuthStateChanged:signed _out"); } // ... } }; } @Override public void onStart() { super.onStart(); mAuth.addAuthStateListener(mAuthListener); } @Override public void onStop() { super.onStop(); if (mAuthListener != null) { mAuth.removeAuthStateListener(mAuthListener); } } }
问题原因
错误日志明确指出,在调用FirebaseAuth.AuthStateListener.onAuthStateChanged时,listener对象为null。查看代码逻辑:
mAuthListener仅在setupFirebaseAuth()方法中初始化setupFirebaseAuth()是在用户点击注册按钮后的doRegister()方法里才被调用- 但Activity的
onStart()方法会在页面打开时立即执行,此时mAuthListener还未被初始化,调用mAuth.addAuthStateListener(mAuthListener)就会触发空指针异常。
另外还有一个潜在问题:username变量在onCreate()时获取输入框文本(此时输入框为空),后续在setupFirebaseAuth()中使用的是这个空值,而非用户实际输入的用户名。
修复方案
1. 提前初始化AuthStateListener
将setupFirebaseAuth()的调用移到onCreate()方法中,确保在onStart()执行前mAuthListener已完成初始化:
修改onCreate()方法末尾:
mAuth=FirebaseAuth.getInstance(); setupFirebaseAuth(); // 提前初始化AuthStateListener btnRegister.setOnClickListener(view -> ValidateDataandDoRegister());
同时删除doRegister()方法中的setupFirebaseAuth();调用。
2. 修正username变量的取值逻辑
在setupFirebaseAuth()的onDataChange方法中,直接从输入框获取最新的用户名,避免使用初始化时的空值:
// 替换原username = username + append; String inputUsernameStr = inputUsername.getText().toString().trim(); String finalUsername = firebaseMethods.checkIfUsernameExists(inputUsernameStr, dataSnapshot) ? inputUsernameStr + append : inputUsernameStr;
后续存储用户数据时使用finalUsername即可。
3. 优化AuthStateListener逻辑
由于注册成功后会调用sendVerificationEmail()并执行mAuth.signOut(),AuthStateListener会检测到用户登出,此时不需要弹出失败提示,可调整逻辑避免误导用户:
@Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { FirebaseUser user=firebaseAuth.getCurrentUser(); if (user != null) { // 用户已登录,执行数据库存储逻辑 Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid()); // ... 原数据库操作逻辑 } else { // 用户登出,此处无需提示失败,因为是主动登出 Log.d(TAG, "onAuthStateChanged:signed_out"); } }
内容的提问来源于stack exchange,提问作者Nithin reddy
相关产品推荐
相关产品推荐

