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

MVVM架构下Firebase登录请求重复触发问题求助:错误提示后点击登录按钮触发3次请求

解决登录按钮多次点击后错误日志重复输出及Firebase请求过多问题

兄弟,我一眼就看出问题所在了——你每次点击登录按钮时,都在重复注册authState的Observer,而且每次点击都会触发新的登录请求,这就导致了两个麻烦:

  • 多次点击后,多个Observer同时盯着authState的变化,所以错误状态一来,所有Observer都会执行onChanged里的日志和Toast,自然就重复输出了
  • 每次点击都发新的登录请求,短时间内点几次就发几次请求,Firebase的请求频率限制自然就触发了

给你两个关键修复步骤,包解决:

1. 把Observer注册移到点击事件外面

Observer只需要注册一次,放在Activity的onCreate方法里就行,不用每次点击按钮都新建一个。这样不管点多少次,只有一个Observer在监听状态变化。

修改后的Activity代码示例:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityLoginRegisterBinding.inflate(layoutInflater)
    setContentView(binding.root)

    // 在这里一次性注册Observer,而不是点击事件内重复注册
    registerLoginViewModel.authState.observe(this@LoginRegisterActivity) { loginState ->
        when (loginState) {
            is AuthState.Success -> {
                hideLoadingScreen()
                Toast.makeText(this@LoginRegisterActivity,"Welcome Back!",Toast.LENGTH_SHORT).show()
                startActivity(Intent(this@LoginRegisterActivity, MainActivity::class.java))
                finish()
            }
            is AuthState.AuthError -> {
                hideLoadingScreen()
                Log.e("Error:","Error Message: ${loginState.message}")
                Toast.makeText(this@LoginRegisterActivity,loginState.message,Toast.LENGTH_SHORT).show()
            }
            AuthState.Loading -> {
                showLoadingScreen()
            }
            else -> {}
        }
    }

    binding.loginButton.setOnClickListener {
        val emailEditText = binding.emailAddressEditText.text.toString()
        val passwordEditText = binding.passwordEditText.text.toString()
        // 这里只触发登录请求,不再注册Observer
        registerLoginViewModel.loginUser(emailEditText, passwordEditText)
    }
}

2. 给登录按钮加防重复点击限制

为了彻底避免用户短时间内多次点击导致重复发请求,我们可以加一个标记位,在登录过程中禁用按钮点击:

首先在Activity里定义一个标记变量:

private var isLoggingIn = false

然后修改点击事件和Observer逻辑:

binding.loginButton.setOnClickListener {
    if (isLoggingIn) return@setOnClickListener // 如果正在登录,直接返回
    isLoggingIn = true

    val emailEditText = binding.emailAddressEditText.text.toString()
    val passwordEditText = binding.passwordEditText.text.toString()
    registerLoginViewModel.loginUser(emailEditText, passwordEditText)
}

// 然后在Observer的onChanged里重置标记
registerLoginViewModel.authState.observe(this@LoginRegisterActivity) { loginState ->
    when (loginState) {
        is AuthState.Success -> {
            isLoggingIn = false
            hideLoadingScreen()
            Toast.makeText(this@LoginRegisterActivity,"Welcome Back!",Toast.LENGTH_SHORT).show()
            startActivity(Intent(this@LoginRegisterActivity, MainActivity::class.java))
            finish()
        }
        is AuthState.AuthError -> {
            isLoggingIn = false
            hideLoadingScreen()
            Log.e("Error:","Error Message: ${loginState.message}")
            Toast.makeText(this@LoginRegisterActivity,loginState.message,Toast.LENGTH_SHORT).show()
        }
        AuthState.Loading -> {
            showLoadingScreen()
        }
        else -> {}
    }
}

这样修改后,不管用户怎么点,同一时间只会有一个登录请求在执行,而且Observer只会触发一次状态回调,错误日志重复输出和Firebase请求过多的问题就都解决了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 08:47:41