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

集成Firebase Authentication后App启动相关Activity时崩溃

问题原因

这个崩溃和Firebase Authentication集成没有关系,属于Android Activity生命周期使用错误。
从Logcat堆栈可以定位到崩溃触发点:com.example.flimer.SignUp.<init>(SignUp.kt:15),也就是SignUp Activity的实例构造阶段就抛出了空指针。Activity在构造阶段还没有完成Context绑定,也没有加载Window和布局树,此时任何依赖Context、依赖布局的方法(比如findViewById、获取主题、弹Toast等)都会因为Context为null触发崩溃。
你误以为是Firebase导致的问题,只是因为出问题的页面刚好包含Firebase相关代码。

现有代码的问题清单
  • 直接触发崩溃的问题:你实际运行的SignUp代码里,存在成员变量声明时直接调用findViewById赋值的写法(对应SignUp.kt第15行),这行代码会在Activity实例化时立刻执行,早于onCreate生命周期、早于setContentView调用,必然触发空指针。你贴出的代码把findViewById写在了onCreate里,说明运行的代码和贴出的版本不一致,优先检查类的成员属性定义。
  • 输入读取逻辑错误:你在setContentView执行后立刻读取三个输入框的文本,此时页面刚完成渲染,用户还没有任何输入操作,后续点击注册按钮时拿到的永远是空字符串,根本无法获取用户实际输入的内容。
  • 表单校验逻辑错误:原校验逻辑只有当邮箱和密码同时为空时才提示,单独漏填邮箱、单独漏填密码都不会触发提示,会直接把空值传给Firebase注册接口。
  • 加载弹窗逻辑错误:原dismiss()方法每次都会新建一个Dialog实例再执行关闭,和之前弹出的加载弹窗不是同一个对象,永远无法关闭已经显示的加载框。
  • 无用冗余逻辑:闪屏页里判断Build.VERSION.SDK_INT < 16的逻辑完全无效,API 16是2012年发布的Android 4.1版本,目前线上几乎没有运行该版本以下的设备,且全屏Flag的设置应该放在setContentView之前才会生效。
修复方案
  1. 所有findViewById调用必须放在setContentView执行之后,绝对不能在类成员声明位置直接调用。
  2. 输入框的文本内容必须在点击按钮触发注册时再读取,不要在onCreate阶段提前读取。
  3. 持有加载弹窗的全局实例,不要每次操作都新建Dialog对象。
  4. 修正表单校验的判断条件,把且逻辑改成或逻辑,覆盖所有漏填场景。

修复后的SignUp代码如下:

class SignUp : AppCompatActivity() {
    // 仅声明控件和对象,不做初始化
    private lateinit var etEmail: EditText
    private lateinit var etPass: EditText
    private lateinit var etPass2: EditText
    private lateinit var btn: Button
    private lateinit var loadingDialog: Dialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_up)

        // setContentView之后再初始化所有控件
        etEmail = findViewById(R.id.et_email)
        etPass = findViewById(R.id.pass)
        etPass2 = findViewById(R.id.et_pass2)
        btn = findViewById(R.id.btn_create)
        loadingDialog = Dialog(this).apply {
            setContentView(R.layout.custom_dialog)
            setCancelable(false)
        }

        btn.setOnClickListener {
            // 点击时再读取用户输入的内容
            val email = etEmail.text.toString().trim()
            val pass = etPass.text.toString().trim()
            val pass2 = etPass2.text.toString().trim()

            if (isValid(email, pass, pass2)){
                loadingDialog.show()
                signUp(email, pass)
            }
        }
    }

    private fun isValid(email: String, pass: String, pass2: String ): Boolean{
        return when {
            email.isEmpty() || pass.isEmpty() || pass2.isEmpty() -> {
                Toast.makeText(this, "请填写所有必填项", Toast.LENGTH_SHORT).show()
                false
            }
            pass != pass2 -> {
                Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show()
                false
            }
            else -> true
        }
    }

    private fun signUp(email: String, pass: String){
        val auth: FirebaseAuth = Firebase.auth
        auth.createUserWithEmailAndPassword(email,pass).addOnCompleteListener {
            loadingDialog.dismiss()
            if (it.isSuccessful){
                Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show()
                // 注册成功后可以跳转到主页
            }else{
                Toast.makeText(this, it.exception?.message ?: "注册失败,请稍后重试", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

闪屏页可以把冗余的版本判断去掉,调整全屏逻辑的位置:

class Startscreen : AppCompatActivity() {
    private lateinit var auth: FirebaseAuth

    override fun onCreate(savedInstanceState: Bundle?) {
        // 设置全屏要在setContentView之前调用
        window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_startscreen)

        auth = Firebase.auth
        val user = auth.currentUser

        // 用主线程Handler,避免内存泄漏
        Handler(Looper.getMainLooper()).postDelayed({
            val target = if (user != null) MainActivity::class.java else SignUp::class.java
            startActivity(Intent(this@Startscreen, target))
            finish()
        }, 2000)
    }
}

内容的提问来源于stack exchange,提问作者Victor kiptoo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:57:23