【问题标题】:Firebase make 3 requests at a time MVVMFirebase 一次发出 3 个请求 MVVM
【发布时间】:2022-01-09 14:46:45
【问题描述】:

所以我开始构建一个聊天应用程序,现在我在注册屏幕。

每次我按下登录按钮,请求只发送一次,就像它应该做的那样。 当我返回错误消息(例如“您的密码不正确”)时,问题就开始了,在我收到错误消息后,我再次使用相同的错误密码按下登录按钮,我收到了我所做的日志错误,但它同时显示 3 次,firebase 告诉我尝试次数过多....

这就是我所做的:

视图模型:

    private val _authState by lazy { MutableLiveData<AuthState>(AuthState.Loading) }
    val authState: LiveData<AuthState> = _authState

fun loginUser(emailAddress: String, password: String) {

        if (!isEmailAddressValid(emailAddress)) {
            _authState.value = AuthState.AuthError("Invalid email")
            return

        } else if (password.isEmpty()) {
            _authState.value = AuthState.AuthError("Password field can't be empty")
            return

        } else if (emailAddress.isEmpty()) {
            _authState.value = AuthState.AuthError("Email field can't be empty")
            return

        }


            auth.signInWithEmailAndPassword(emailAddress, password).addOnCompleteListener { task ->

                if (task.isSuccessful) {
                    _authState.value = AuthState.Success
                } else {
                    task.exception?.let {
                        _authState.value = AuthState.AuthError(it.localizedMessage)
                    }
                }

            }
    }

这是活动:

binding.loginButton.setOnClickListener {

            val emailEditText = binding.emailAddressEditText.text.toString()
            val passwordEditText = binding.passwordEditText.text.toString()


                registerLoginViewModel.loginUser(emailEditText, passwordEditText)

                registerLoginViewModel.authState.observe(this@LoginRegisterActivity, object : Observer<AuthState?> {
                    override fun onChanged(loginState: AuthState?) {
                        when (loginState) {

                            is AuthState.Success -> {
                                hideLoadingScreen()
                                Toast.makeText(this@LoginRegisterActivity,"Welcome Back!",Toast.LENGTH_SHORT).show()
                                Intent(this@LoginRegisterActivity, MainActivity::class.java)
                                finish()
                            }

                            is AuthState.AuthError -> {
                                hideLoadingScreen()
                                Log.e("Error:","Error Message: ${loginState.message}") // This line returns 3 times after the second attempt
                                Toast.makeText(this@LoginRegisterActivity,loginState.message,Toast.LENGTH_SHORT).show()
                            }
                            else -> {
                                showLoadingScreen()
                            }
                        }

                    }
                })
        }

谢谢!

【问题讨论】:

  • 请注意:LiveData.observe(...) 不需要在任何类型的侦听器中。您可以在 API 调用之前在 Activity 的onCreate() 中观察。就像现在在您的代码中一样,每次调用您的点击侦听器时,您都会添加一个新的观察者。
  • 听起来像一个答案@rupinderjeet! ??????
  • 谢谢@rupinderjeet!
  • @rupinderjeet 同意 Frank van Puffelen 的观点。您应该添加一个答案。

标签: android kotlin mvvm firebase-authentication android-viewmodel


【解决方案1】:

LiveData.observe(...) 不需要在任何类型的侦听器中。您可以在 API 调用之前在 Activity 的onCreate() 中观察。就像现在在您的代码中一样,每次调用您的点击侦听器时,您都会添加一个新的观察者。

这是一个小例子:

class FruitsActivity : AppCompatActivity {

    private val binding by lazy {
        FruitsActivityBinding.inflate(layoutInflater)
    } 

    private val fruitsViewModel by viewModels<FruitsViewModel>() 

    @Override
    fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        // Observe from fruitsViewModel.fruits
        fruitsViewModel.fruits.observe(this) { fruitList ->
            // Use `fruitList` in your adapter
        }

        // Fetch fruits on tap of a button
        binding.loadFruitsButton.setOnClickListener {
            fruitsViewModel.fetchFruits()
        }
    }
}

class FruitsViewModel : ViewModel() {

    private val _fruits = MutableLiveData<List<Fruit>>()
    val fruits: LiveData<List<Fruit>> = _fruits 

    fun fetchFruits() {
        viewModelScope.launch {
            // `someRepository` can be anything that calls an API 
            // or queries a database to get the required data.
            // Repository Pattern + Coroutines recommended
            val fruitList = someRepository.fetchFruits()

            // if needed, perform any filters or modifications to `fruitList` here

            // set the result data on LiveData
            _fruits.value = fruitList
        }
    }
}

所以,这就是发生的事情:

  • 活动启动。
  • 初始化bindingfruitsViewModel
  • fruits 上从fruitsViewModel 添加一个Observer
  • 在按钮上设置点击监听器以加载水果
  • 当您点击按钮时,fruitsViewModel 会获取水果并将结果数据设置到 LiveData (_fruits)。
  • LiveData 找到它的观察者并通知他们新数据。

如果您有任何问题或有什么问题,请告诉我。我直接在此文本字段中编写代码,因此可能有一个点、逗号或冒号错位或丢失。

【讨论】:

  • 非常感谢您的详细解答!
猜你喜欢
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 2020-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多