Android 如何侦听失败的登录尝试-Kotlin MVVM
因此,我遵循了“yoursTruly”的建议,在我的活动中创建了一个AuthStateListener(如下所述:) 这非常有效,因为活动只是在侦听身份验证,如果有人登录并且片段只是通过ViewModel调用signIn(电子邮件、密码),则会转移到下一个活动 但是,无法找到查找失败的登录尝试的方法(因此UI看起来好像没有响应) 我的结构如下:活动->片段->视图模型->存储库 我正在使用数据绑定和导航 活动Android 如何侦听失败的登录尝试-Kotlin MVVM,android,kotlin,mvvm,firebase-authentication,Android,Kotlin,Mvvm,Firebase Authentication,因此,我遵循了“yoursTruly”的建议,在我的活动中创建了一个AuthStateListener(如下所述:) 这非常有效,因为活动只是在侦听身份验证,如果有人登录并且片段只是通过ViewModel调用signIn(电子邮件、密码),则会转移到下一个活动 但是,无法找到查找失败的登录尝试的方法(因此UI看起来好像没有响应) 我的结构如下:活动->片段->视图模型->存储库 我正在使用数据绑定和导航 活动 class LoginActivity : AppCompatActivity(),
class LoginActivity : AppCompatActivity(), FirebaseAuth.AuthStateListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_activity)
}
override fun onStart() {
super.onStart()
FirebaseAuth.getInstance().addAuthStateListener(this)
}
override fun onStop() {
super.onStop()
FirebaseAuth.getInstance().removeAuthStateListener(this)
}
override fun onAuthStateChanged(firebaseAuth: FirebaseAuth) {
// Will only fire if state has changed!
if (FirebaseAuth.getInstance().currentUser == null) {
Toast.makeText(this,"Welcome to the Locators App!\n\nPlease login to continue", Toast.LENGTH_LONG).show()
return
}
firebaseAuth.currentUser?.getIdToken(true)
?.addOnSuccessListener { result ->
val idToken = result.token
Toast.makeText(this,"User Signed In", Toast.LENGTH_LONG).show()
Log.d(TAG, "GetTokenResult result (check this at https://jwt.io/ = $idToken")
goToSiteActivity()
}
}
private fun goToSiteActivity() {
val intent = Intent(this, SiteActivity::class.java)
startActivity(intent)
finish()
}
}
class FirestoreRepository {
var firebaseAuth = FirebaseAuth.getInstance()
var firebaseUser = firebaseAuth.currentUser
var failedLogin: Boolean = false
fun loginUser(email: String, password: String) {
failedLogin = false
firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
if (it.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithEmail:success")
} else {
// If sign in fails, display a message to the user.
Log.d(TAG, "signInWithEmail:failure", it.exception)
failedLogin = true
}
}
}
}
片段
class LoginFragment : Fragment() {
private lateinit var loginViewModel: LoginViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val binding: LoginFragmentBinding = DataBindingUtil.inflate(
inflater, R.layout.login_fragment, container, false)
binding.apply {
loginPasswordResetText.setOnClickListener{
findNavController().navigate(R.id.action_loginFragment_to_loginPasswordResetFragment)
}
loginButton.setOnClickListener{
loginProgressBar.visibility = View.VISIBLE
val email = loginEmailEditText.text.toString()
val password = loginPasswordEditText.text.toString()
if(validateForm(email, password)) {
loginViewModel.loginUser(email, password)
}
loginProgressBar.visibility = View.GONE
}
loginNewUserText.setOnClickListener{
findNavController().navigate(R.id.action_loginFragment_to_loginUserRegisterFragment)
}
}
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
loginViewModel = ViewModelProviders.of(requireActivity()).get(LoginViewModel::class.java)
}
private fun validateForm(email: String, password: String): Boolean {
var validForm = true
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
loginEmailEditText.error = "Please enter valid email address!"
validForm = false
} else loginEmailEditText.error = null
if (password.isEmpty()) {
loginPasswordEditText.error = "Please enter password!"
validForm = false
} else loginPasswordEditText.error = null
Log.d(TAG,"validateForm: (email = $email, password = $password, validateForm = $validForm)")
return validForm
}
}
视图模型
class LoginViewModel : ViewModel() {
fun loginUser (email: String, password: String) {
firestoreRepository.loginUser(email, password)
}
}
存储库
class LoginActivity : AppCompatActivity(), FirebaseAuth.AuthStateListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_activity)
}
override fun onStart() {
super.onStart()
FirebaseAuth.getInstance().addAuthStateListener(this)
}
override fun onStop() {
super.onStop()
FirebaseAuth.getInstance().removeAuthStateListener(this)
}
override fun onAuthStateChanged(firebaseAuth: FirebaseAuth) {
// Will only fire if state has changed!
if (FirebaseAuth.getInstance().currentUser == null) {
Toast.makeText(this,"Welcome to the Locators App!\n\nPlease login to continue", Toast.LENGTH_LONG).show()
return
}
firebaseAuth.currentUser?.getIdToken(true)
?.addOnSuccessListener { result ->
val idToken = result.token
Toast.makeText(this,"User Signed In", Toast.LENGTH_LONG).show()
Log.d(TAG, "GetTokenResult result (check this at https://jwt.io/ = $idToken")
goToSiteActivity()
}
}
private fun goToSiteActivity() {
val intent = Intent(this, SiteActivity::class.java)
startActivity(intent)
finish()
}
}
class FirestoreRepository {
var firebaseAuth = FirebaseAuth.getInstance()
var firebaseUser = firebaseAuth.currentUser
var failedLogin: Boolean = false
fun loginUser(email: String, password: String) {
failedLogin = false
firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
if (it.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithEmail:success")
} else {
// If sign in fails, display a message to the user.
Log.d(TAG, "signInWithEmail:failure", it.exception)
failedLogin = true
}
}
}
}
这个问题与一个更大的查询有关,如果您在Repo中创建LiveData,您如何从ViewModel中观察(即,您使用什么作为LifeCycleOwner?),但我将另外问一个问题。AuthStateListener不足以确定登录何时失败。它只会在用户状态在登录和注销之间发生变化时通知您 您必须使用firebaseAuth.Signin with Email和Password的结果来确定登录是否失败。看起来您已经有了一些代码来处理这种情况,但是除了设置属性之外,您并没有对错误进行太多处理
您应该做的是让您的
logiuser
ViewModel方法返回一个LiveData,当登录成功或失败时会收到通知。您必须使用Email和Password将呼叫连接到登录,以更改该LiveData的状态,并且您的视图必须观察该LiveData,以便在必要时向用户显示消息。此问题看起来像是特定于android的。如果理解正确,请添加“android”标记。android添加..嗨,道格,再次感谢你的回复-我已经尝试过了,但我正在努力处理ViewModel中的代码。具体而言,观察者的生命周期所有者。。当虚拟机被销毁时,我是否应该使用ObserveForver并手动删除observer?如果这对您有效的话。如果您有新问题,我建议发布一个新问题来解释问题是什么,以及哪些问题没有按照您预期的方式工作。我的帖子已经过审核(希望此评论可以!),但为了完整性,我在这里更新了我的问题,并提供了解决方案: