You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Firebase登录模块空指针异常问题排查求助

Firebase Android登录功能空指针异常解决

问题概述

开发基于Firebase的Android登录功能时,在activity_singIn的onClick方法中调用singInPresenter.singInUser(v)触发空指针异常,报错信息如下:

2022-09-18 17:30:51.785 3811-3811/com.example.Natour21 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.Natour21, PID: 3811
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.NaTour21.Presenter.Activity.SingInPresenter.singInUser(android.view.View)' on a null object reference
at com.example.NaTour21.View.Activity.activity_singIn$2.onClick(activity_singIn.java:61)

核心问题分析

  • Presenter未初始化:activity_singIn中声明了SingInPresenter singInPresenter,但从未实例化,调用方法时触发空指针。
  • Presenter设计错误:SingInPresenter继承AppCompatActivity,不符合MVP架构中Presenter仅处理业务逻辑的职责定位。
  • Firebase方法误用:登录应调用signInWithEmailAndPassword,代码错误使用了注册方法createUserWithEmailAndPassword。
  • 视图组件未关联:Presenter内的EmailLgn、PasswordLgn等控件未绑定Activity视图,后续会触发新的空指针。

修复步骤

1. 重构Presenter为普通类

将SingInPresenter改为普通类,通过构造函数接收上下文和必要视图组件,专注处理登录业务逻辑:

package com.example.NaTour21.Presenter.Activity;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Handler;
import android.view.View;
import android.widget.ProgressBar;

import androidx.annotation.NonNull;

import com.example.NaTour21.View.Activity.activity_Home;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;

public class SingInPresenter {

    private Context mContext;
    private ProgressBar mProgressBar;
    private FirebaseAuth mAuth;

    public SingInPresenter(Context context, ProgressBar progressBar) {
        mContext = context;
        mProgressBar = progressBar;
        mAuth = FirebaseAuth.getInstance();
    }

    public void singInUser(String email, String password, View view) {
        mProgressBar.setVisibility(View.VISIBLE);

        mAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            new Handler().postDelayed(() -> navigateToHome(), 3000);
                        } else {
                            mProgressBar.setVisibility(View.GONE);
                            String errorMsg = "登录失败:" + task.getException().getMessage();
                            showErrorSnackbar(view, errorMsg);
                        }
                    }
                });
    }

    private void navigateToHome() {
        Intent intent = new Intent(mContext, activity_Home.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mContext.startActivity(intent);
    }

    public void checkCurrentUser() {
        FirebaseUser currentUser = mAuth.getCurrentUser();
        if (currentUser != null) {
            navigateToHome();
        }
    }

    private void showErrorSnackbar(View view, String message) {
        Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
        snackbar.setBackgroundTint(Color.WHITE);
        snackbar.setTextColor(Color.BLACK);
        snackbar.show();
    }
}

2. 修正Activity逻辑并初始化Presenter

在activity_singIn中实例化Presenter,调整登录逻辑并修正错误判断:

package com.example.NaTour21.View.Activity;

import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;

import androidx.appcompat.app.AppCompatActivity;

import com.example.NaTour21.Presenter.Activity.SingInPresenter;
import com.example.NaTour21.R;
import com.google.android.material.snackbar.Snackbar;

import android.view.View;

public class activity_singIn extends AppCompatActivity{

    private EditText EmailLgn,PasswordLgn;
    private Button loginLgn;
    private Button registratiLgn;
    private SingInPresenter singInPresenter;
    private ProgressBar progressbar;
    String[] messaggio = {"请填写所有字段",
                          "登录成功",
                          "邮箱格式无效",
                           "密码长度不能少于6位"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singin);

        getSupportActionBar().hide();
        initializeComponent();
        // 初始化Presenter
        singInPresenter = new SingInPresenter(this, progressbar);

        registratiLgn.setOnClickListener(v -> {
            Intent intent = new Intent(activity_singIn.this, activity_singUp.class);
            startActivity(intent);
        });

        loginLgn.setOnClickListener(v -> {
            String email = EmailLgn.getText().toString().trim();
            String password = PasswordLgn.getText().toString().trim();

            if (email.isEmpty() || password.isEmpty()) {
                showSnackbar(v, messaggio[0]);
            } else if (!isValidEmail(email)) {
                showSnackbar(v, messaggio[2]);
            } else if (password.length() < 6) { // 修正原逻辑的判断错误
                showSnackbar(v, messaggio[3]);
            } else {
                showSnackbar(v, messaggio[1]);
                // 传递邮箱密码给Presenter处理
                singInPresenter.singInUser(email, password, v);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 检查已登录用户
        singInPresenter.checkCurrentUser();
    }

    private boolean isValidEmail(String email) {
        return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
    }

    private void initializeComponent() {
        registratiLgn = findViewById(R.id.btRegistratiLgn);
        EmailLgn = findViewById(R.id.tilEmailLgn);
        PasswordLgn = findViewById(R.id.tilPasswordLgn);
        loginLgn = findViewById(R.id.btLoginLgn);
        progressbar = findViewById(R.id.progressbarLgn);
    }

    private void showSnackbar(View view, String message) {
        Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
        snackbar.setBackgroundTint(Color.WHITE);
        snackbar.setTextColor(Color.BLACK);
        snackbar.show();
    }
}

3. 修正布局中ProgressBar的属性

布局中ProgressBar误用ConstraintLayout属性,改为LinearLayout适配的属性:

<ProgressBar
    android:id="@+id/progressbarLgn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:visibility="invisible" />

关键修复点总结

  • 实例化SingInPresenter,解决空指针问题。
  • 重构Presenter为普通类,遵循MVP架构职责分离原则。
  • 替换Firebase方法为正确的登录接口signInWithEmailAndPassword。
  • 修正Activity中密码长度的判断逻辑(原逻辑写反导致错误提示)。
  • 将视图数据从Activity传递给Presenter,避免Presenter直接操作视图。

内容的提问来源于stack exchange,提问作者Fabiola Salomone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:40:31