Android ArrayList大小为零

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

嘿,我试图用AndroidKotlin编写一个简单的测试,当我尝试使用它时,数组似乎是空的。我从Firebase数据库获取数据,并将其记录在LogCat中,但当我尝试获取阵列的大小时,它显示为0

我该怎么做有什么指导吗

这是我的密码:

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发布另一个新问题,以便我和其他用户可以帮助您。