我正在 Kotlin 中为 android 开发一个应用程序,并编写重置密码片段,其中逻辑如下:
用户输入电子邮件地址以重置密码。 输入电子邮件并按下"发送重置代码"后,ViewModel 函数 触发forgetPasswordViewModel.sendAuthCode()
,通过存储库向房间数据库发送查询,以检查房间数据库中是否存在包括电子邮件地址在内的用户数据,如果该电子邮件地址存在由非空结果指示,系统将检索密码的重置代码(authCode)并通过电子邮件发送给用户。如果系统中不存在电子邮件地址(由空用户数据指示),则视图模型中validEmail
的布尔变量设置为true
。这有助于我在忘记密码片段中生成适当的吐司消息。
我在 ForgetPassword 片段中调用该方法forgetPasswordViewModel.sendAuthCode()
,然后检查validEmail
变量,该变量将指示系统中是否已存在电子邮件,但是该变量validEmail
始终返回false
,因为协程forgetPasswordViewModel.sendAuthCode()
仍在后台线程中运行,并且直到那时validEmailyet
不会更新布尔变量, 因此,在运行片段的主线程上,代码继续运行以下语句,该语句从 ViewModel 检索validEmail
,此时该语句仍为 false,因为协程函数forgetPasswordViewModel.sendAuthCode()
尚未将变量设置为 true。
Kotlin 中是否有任何函数可供我使用,以便我的代码将等到协程完成执行并更新变量,然后再继续执行代码。我在 StackOverFlow 上看到了一些解决方案,人们建议使用 join(),但我只有一个协程,布尔变量validEmail
是 ViewModel 范围变量。谁能引导我朝着正确的方向前进。这是我的代码:
查看模型:
class ForgetPasswordViewModel(val repository: Repository) : ViewModel() {
//Variable to contain user email address
lateinit var emailAddress: String
var validEmail: Boolean = false
//Getting instance of Repository
val repo = Repository()
//Send Password reset code to email
fun sendAuthCode() {
viewModelScope.launch {
val userData = repo.getUserDataByEmail(emailAddress)
if (userData != null) {
val authCode = userData.authCode
//Send email to new user with account details
val sender = SendMail(
AppContext.appContext!!,
emailAddress,
"Password reset code",
"Dear ${userData.firstName},nn" +
" This is your reset code.nn +
"Password reset code: $authCode n"
)
sender.execute()
validEmail = true //here I set it to true to indicate that things went well
}
}
}
}
以下是ForgetPassword Fragment的片段:
// Set onClickListener to btnRequestPassword button
viewBinding.btnRequestPassword.setOnClickListener{
forgetPasswordViewModel.emailAddress = emailAddress.text.toString()
if(forgetPasswordViewModel.emailAddress.length < 3) { //The theoretical minimum length of any email address is 3
ValidationChecks.showToast("Enter valid email address",context)
} else{
forgetPasswordViewModel.sendAuthCode()
if(!forgetPasswordViewModel.validEmail){
Toast.makeText(context, "Email not found in the system",Toast.LENGTH_SHORT)
} else {
Toast.makeText(context, "Password reset code sent successfully!",Toast.LENGTH_SHORT)
}
如果有人能把我推向正确的方向,我将不胜感激。 亲切问候 萨利克
由于您期望同步行为,因此您可以在片段中启动协程并使sendAuthCode
函数挂起。
片段:
...
viewLifecycleOwner.lifecycleScope.launch {
val validEmail = forgetPasswordViewModel.sendAuthCode()
if(!validEmail){
Toast.makeText(context, "Email not found in the system",Toast.LENGTH_SHORT)
} else {
Toast.makeText(context, "Password reset code sent successfully!",Toast.LENGTH_SHORT)
}
}
...
视图模型:
suspend fun sendAuthCode(): Boolean {
val userData = repo.getUserDataByEmail(emailAddress)
if (userData != null) {
val authCode = userData.authCode
//Send email to new user with account details
val sender = SendMail(
AppContext.appContext!!,
emailAddress,
"Password reset code",
"Dear ${userData.firstName},nn" +
" This is your reset code.nn +
"Password reset code: $authCode n"
)
sender.execute()
return true
}
return false
}
确保您的 DAO 方法处于挂起状态,以便它们从主线程中运行。或者,如果在操作过程中存在阻塞调用,viewLifecycleOwner.lifecycleScope.launch {...}
在主线程上运行,则更改协程上下文。像这样的事情就可以了:
suspend fun sendAuthCode(): Boolean = withContext(Dispatchers.IO) {
...
}