Android ArrayList大小为零
嘿,我试图用AndroidKotlin编写一个简单的测试,当我尝试使用它时,数组似乎是空的。我从Firebase数据库获取数据,并将其记录在LogCat中,但当我尝试获取阵列的大小时,它显示为0 我该怎么做有什么指导吗 这是我的密码:Android ArrayList大小为零,android,firebase,firebase-realtime-database,kotlin,Android,Firebase,Firebase Realtime Database,Kotlin,嘿,我试图用AndroidKotlin编写一个简单的测试,当我尝试使用它时,数组似乎是空的。我从Firebase数据库获取数据,并将其记录在LogCat中,但当我尝试获取阵列的大小时,它显示为0 我该怎么做有什么指导吗 这是我的密码: import android.app.ProgressDialog import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log i
import android.app.ProgressDialog
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import com.google.firebase.database.*
import kotlinx.android.synthetic.main.activity_quiz.*
class QuizActivity : AppCompatActivity() {
var quizArray: ArrayList<QuizItem> = ArrayList()
private var database: FirebaseDatabase? = null
private var databaseReference: DatabaseReference? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz)
database = FirebaseDatabase.getInstance()
databaseReference = database!!.getReference("quiz")
var dbRef = databaseReference!!.child("mod1")
val progress = ProgressDialog(this)
progress.setMessage("Loading")
progress.isIndeterminate
var valueEventListener: ValueEventListener = object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
var contentSnapshot: DataSnapshot = p0
var contentChildren: Iterable<DataSnapshot> = contentSnapshot.children
for (content: DataSnapshot in contentChildren){
var quizItem: QuizItem = content.getValue(QuizItem::class.java)!!
Log.d("\n Received Data", "data: statement = "+quizItem.statement
+" id = "+quizItem.id
+" correctOption = "+quizItem.correctOption
+" optionA"+quizItem.optionA
+" optionB"+quizItem.optionB
+" optionC"+quizItem.optionC
+" optionD"+quizItem.optionD
+" \n ")
quizArray.add(quizItem)
Toast.makeText(applicationContext, "Item added for ID = "+quizItem.id, Toast.LENGTH_SHORT).show()
}
print(quizArray)
progress.dismiss()
Log.d("Data Received", "this@QuizActivity")
Log.d("Progress Bar", "this@QuizActivity Progress Bar Dismissed")
}
}
dbRef!!.addValueEventListener(valueEventListener)
progress.show()
Log.d("Progress Bar", "this@QuizActivity Progress Bar Sent")
Toast.makeText(applicationContext, "Array Size = "+quizArray.size, Toast.LENGTH_SHORT).show()
startQuiz()
}
private fun startQuiz(){
var total: Int = quizArray.size
Toast.makeText(applicationContext, total.toString(), Toast.LENGTH_SHORT).show()
var correct: Int = 0
var incorrect: Int = 0
var done: Int = 0
tv_quiz_total.text = total.toString()
tv_quiz_correct.text = correct.toString()
tv_quiz_incorrect.text = incorrect.toString()
tv_quiz_done.text = done.toString()
var i = 0
while (i<total){
tv_quiz_statement.text = quizArray[i].statement
tv_quiz_opA.text = quizArray[i].optionA
tv_quiz_opB.text = quizArray[i].optionB
tv_quiz_opC.text = quizArray[i].optionC
tv_quiz_opD.text = quizArray[i].optionD
tv_quiz_opA.setOnClickListener {
if (quizArray[i].correctOption == 1){
correct++
done++
tv_quiz_correct.text = correct.toString()
tv_quiz_done.text = done.toString()
i++
} else {
incorrect++
done++
i++
tv_quiz_incorrect.text = incorrect.toString()
}
}
tv_quiz_opB.setOnClickListener {
if (quizArray[i].correctOption == 2){
correct++
done++
tv_quiz_correct.text = correct.toString()
tv_quiz_done.text = done.toString()
i++
} else {
incorrect++
done++
i++
tv_quiz_incorrect.text = incorrect.toString()
}
}
tv_quiz_opC.setOnClickListener {
if (quizArray[i].correctOption == 3){
correct++
done++
tv_quiz_correct.text = correct.toString()
tv_quiz_done.text = done.toString()
i++
} else {
incorrect++
done++
i++
tv_quiz_incorrect.text = incorrect.toString()
}
}
tv_quiz_opD.setOnClickListener {
if (quizArray[i].correctOption == 4){
correct++
done++
tv_quiz_correct.text = correct.toString()
tv_quiz_done.text = done.toString()
i++
} else {
incorrect++
done++
i++
tv_quiz_incorrect.text = incorrect.toString()
}
}
}
}
}
谢谢Firebase API是异步的,这意味着onDataChange函数在调用后立即返回,并且它返回的任务的回调将在稍后调用。无法保证需要多长时间。因此,在数据可用之前,可能需要几百毫秒到几秒钟的时间。由于该方法会立即返回,因此您试图在此方法之外使用的quizArray ArrayList将始终为空,因为数据尚未完成加载
基本上,您正在尝试同步使用来自异步API的值。那不是个好主意。您应该按照预期异步处理API
这个问题的一个快速解决方法是只在回调中使用ArrayList的值。如果您想在外部使用它,我建议您查看我的anwser的最后一部分,其中我已经解释了如何使用自定义回调来完成此操作。正如Alex Mamo所指出的,您正在尝试同步访问数组,而填充数组的函数是异步函数 尝试在onDataChange方法内调用startQuiz函数。有点像这样:
var valueEventListener: ValueEventListener = object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
var contentSnapshot: DataSnapshot = p0
var contentChildren: Iterable<DataSnapshot> = contentSnapshot.children
for (content: DataSnapshot in contentChildren){
var quizItem: QuizItem = content.getValue(QuizItem::class.java)!!
Log.d("\n Received Data", "data: statement = "+quizItem.statement
+" id = "+quizItem.id
+" correctOption = "+quizItem.correctOption
+" optionA"+quizItem.optionA
+" optionB"+quizItem.optionB
+" optionC"+quizItem.optionC
+" optionD"+quizItem.optionD
+" \n ")
quizArray.add(quizItem)
Toast.makeText(applicationContext, "Item added for ID = "+quizItem.id, Toast.LENGTH_SHORT).show()
}
print(quizArray)
progress.dismiss()
// call the startQuiz function here
startQuiz()
Log.d("Data Received", "this@QuizActivity")
Log.d("Progress Bar", "this@QuizActivity Progress Bar Dismissed")
}
}
我尝试了你的答案,但这样做会导致应用程序变得没有响应,并弹出一个“应用程序没有响应”的弹出窗口。你想关闭它吗?“下面是我修改代码的方式,但这会导致应用程序完全崩溃。我做得对吗?如果应用程序崩溃,就会有堆栈跟踪。请在logcat上查找,并将其添加到您的问题中,或者作为一个commnet,并指出它发生的确切位置。我重新检查了。“startQuiz”函数中的while循环似乎执行了无限次。知道为什么会发生这种情况吗?Alex,我解决了循环执行无限次的问题,但是现在应用程序在我到达数组末尾时就崩溃了。我为最后一次尝试添加了一个条件,但似乎不起作用。你能给我指一下正确的方向吗?下面的代码是一个事实,你得到了另一个错误,这意味着最初的错误消失了,这是一个好消息:但这听起来是一个新问题,基本上应该被视为另一个问题,不能在评论中回答,也不能只使用上面的数据。作为个人猜测,我认为这可能是一个NPE,但为了遵守这个社区的规则,请使用a发布另一个新问题,以便我和其他用户可以帮助您。