当使用应该为真的条件时,我的 Kotlin for 循环不会中断
My Kotlin for-loop does not break when using a condition that is supposed to be true
我有这个 Android 小应用程序,我正在努力注册并将密码和用户名添加到 Firebase 实时数据库。数据库中的所有内容都有一个数字键,有点像数字 1 将设置为用户名和相应的密码,2 也将具有用户名和密码的值,依此类推。因此,我创建了这个从键 1 开始的 for 循环,并检查每个数字键是否已分配给它。如果当前值尚未分配给,新的用户名和密码将存储在那里,当单击注册按钮时循环将中断。
举例说明此循环的工作原理:假设“1”的用户名是“11111”,密码是“11111”,“2”的用户名是“22222”,密码是“ 22222”,而 3 是空的。当 for 循环到达键 3 时,它将写入用户名“33333”和密码“333333”,而另一个键的值的 none 被更改。但是,问题是我已经用 10 个值对此进行了测试,并且在设置值之后,它只是保持设置值超出我要求设置的值。我相信这是因为下面我的 for 循环末尾的条件。我想存储数据是否已在变量中更改并稍后使用它,但这无法正常工作。我已经通过在 if 语句中插入“true”来测试它,它会中断,但是当使用变量时,它不会。
这是我的循环:
var dataHasBeenSet : Boolean = false
for(num in 1..10){
database.child(num.toString()).get().addOnSuccessListener {
if(it.value == "" || it.value == null || it.value == "null") {
database.child(num.toString()).setValue(AccountAdder(password.text.toString(), username.text.toString()))
dataHasBeenSet = true
} else {
dataHasBeenSet = false
//Runs again
}
}.addOnFailureListener {
Toast.makeText(this, "Database cannot be reached at this time. Please try again later", Toast.LENGTH_LONG).show()
}
//Conditional works, however the condition statement does not. Why?
if(dataHasBeenSet){
break
} else {
continue
}
}
是的,实际上正在设置数据,但循环就像 dataHasBeenSet 变量尚未设置为 true,即使我已将其重新分配为真。请记住,底部的条件有效是因为我默认插入了 true,但即使将数据添加到数据库,dataHasBeenSet 变量的值似乎也永远不会改变。
我尝试过的:
- 正在循环内初始化变量
- 将中断条件放在循环的顶部
- 将条件更改为与想要的结果相反
我怎样才能结束这场噩梦?
您需要在 addOnSuccessListener
的回调中移动条件,只要 firebase 查询后台线程结束,只要 OnSuccessListener
回调被触发,就不会触发它。
还有一个问题是for循环在主线程中运行,而firebase方法在工作线程中运行,所以这里你想break/continue来自不同线程的迭代。
I get the error: 'break' or 'continue' breaks across a function or class boundary
这是因为您尝试从 firebase 回调的 lambda 中 return,而编译器不确定它应该在哪里 return。
我鼓励您将使用循环的方法更改为使用侦听器接口,只要您想重复循环(即每当 dataHasBeenSet)就会调用其回调。但实际上在这种方法中您不需要布尔值 dataHasBeenSet
,您可以使用迭代的新值调用侦听器回调。
创建此界面:
interface NextCallListener {
fun onNext(num: Int)
}
在class周围实现它,我假设它的名字是MainActivity
:
class MainActivity: AppCompatActivity() , NextCallListener {
}
然后将您的 firebase 代码移至接受迭代次数和侦听器实例的新方法中:
fun nextCall(num: Int, listener: NextCallListener) {
database.child(num.toString()).get().addOnSuccessListener {
if (it.value == "" || it.value == null || it.value == "null") {
database.child(num.toString())
.setValue(AccountAdder(password.text.toString(), username.text.toString()))
if (num <= 10) // loop max value
listener.onNext(num + 1) // trigger the interface callback for the next iteration
}
}.addOnFailureListener {
Toast.makeText(
this,
"Database cannot be reached at this time. Please try again later",
Toast.LENGTH_LONG
).show()
}
}
然后,只要您想进行 username/password 检查,就在第一次迭代中调用该方法:
nextCall(1, this)
并实现接口回调:
class MainActivity: AppCompatActivity() , NextCallListener {
override fun onNext(num: Int) {
nextCall(num, this)
}
}
我有这个 Android 小应用程序,我正在努力注册并将密码和用户名添加到 Firebase 实时数据库。数据库中的所有内容都有一个数字键,有点像数字 1 将设置为用户名和相应的密码,2 也将具有用户名和密码的值,依此类推。因此,我创建了这个从键 1 开始的 for 循环,并检查每个数字键是否已分配给它。如果当前值尚未分配给,新的用户名和密码将存储在那里,当单击注册按钮时循环将中断。
举例说明此循环的工作原理:假设“1”的用户名是“11111”,密码是“11111”,“2”的用户名是“22222”,密码是“ 22222”,而 3 是空的。当 for 循环到达键 3 时,它将写入用户名“33333”和密码“333333”,而另一个键的值的 none 被更改。但是,问题是我已经用 10 个值对此进行了测试,并且在设置值之后,它只是保持设置值超出我要求设置的值。我相信这是因为下面我的 for 循环末尾的条件。我想存储数据是否已在变量中更改并稍后使用它,但这无法正常工作。我已经通过在 if 语句中插入“true”来测试它,它会中断,但是当使用变量时,它不会。
这是我的循环:
var dataHasBeenSet : Boolean = false
for(num in 1..10){
database.child(num.toString()).get().addOnSuccessListener {
if(it.value == "" || it.value == null || it.value == "null") {
database.child(num.toString()).setValue(AccountAdder(password.text.toString(), username.text.toString()))
dataHasBeenSet = true
} else {
dataHasBeenSet = false
//Runs again
}
}.addOnFailureListener {
Toast.makeText(this, "Database cannot be reached at this time. Please try again later", Toast.LENGTH_LONG).show()
}
//Conditional works, however the condition statement does not. Why?
if(dataHasBeenSet){
break
} else {
continue
}
}
是的,实际上正在设置数据,但循环就像 dataHasBeenSet 变量尚未设置为 true,即使我已将其重新分配为真。请记住,底部的条件有效是因为我默认插入了 true,但即使将数据添加到数据库,dataHasBeenSet 变量的值似乎也永远不会改变。
我尝试过的:
- 正在循环内初始化变量
- 将中断条件放在循环的顶部
- 将条件更改为与想要的结果相反
我怎样才能结束这场噩梦?
您需要在 addOnSuccessListener
的回调中移动条件,只要 firebase 查询后台线程结束,只要 OnSuccessListener
回调被触发,就不会触发它。
还有一个问题是for循环在主线程中运行,而firebase方法在工作线程中运行,所以这里你想break/continue来自不同线程的迭代。
I get the error: 'break' or 'continue' breaks across a function or class boundary
这是因为您尝试从 firebase 回调的 lambda 中 return,而编译器不确定它应该在哪里 return。
我鼓励您将使用循环的方法更改为使用侦听器接口,只要您想重复循环(即每当 dataHasBeenSet)就会调用其回调。但实际上在这种方法中您不需要布尔值 dataHasBeenSet
,您可以使用迭代的新值调用侦听器回调。
创建此界面:
interface NextCallListener {
fun onNext(num: Int)
}
在class周围实现它,我假设它的名字是MainActivity
:
class MainActivity: AppCompatActivity() , NextCallListener {
}
然后将您的 firebase 代码移至接受迭代次数和侦听器实例的新方法中:
fun nextCall(num: Int, listener: NextCallListener) {
database.child(num.toString()).get().addOnSuccessListener {
if (it.value == "" || it.value == null || it.value == "null") {
database.child(num.toString())
.setValue(AccountAdder(password.text.toString(), username.text.toString()))
if (num <= 10) // loop max value
listener.onNext(num + 1) // trigger the interface callback for the next iteration
}
}.addOnFailureListener {
Toast.makeText(
this,
"Database cannot be reached at this time. Please try again later",
Toast.LENGTH_LONG
).show()
}
}
然后,只要您想进行 username/password 检查,就在第一次迭代中调用该方法:
nextCall(1, this)
并实现接口回调:
class MainActivity: AppCompatActivity() , NextCallListener {
override fun onNext(num: Int) {
nextCall(num, this)
}
}