当使用应该为真的条件时,我的 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)
    }
}