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
相关产品推荐
相关产品推荐

