ArrayList的大小为零

时间:2018-11-06 11:12:06

标签: android firebase firebase-realtime-database kotlin

嘿,我试图在Android(Kotlin)中编写一个简单的测验,当我尝试使用它时,数组似乎为空。我从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()
            }
        }

    }

}

}

谢谢

2 个答案:

答案 0 :(得分:1)

Firebase API为asynchronous,这意味着onDataChange()函数在被调用后立即返回,而从其返回的Task的回调将在一段时间后被调用。无法保证需要多长时间。因此,可能需要几百毫秒到几秒钟的时间才能获得该数据。由于该方法会立即返回,因此您尝试在此方法之外使用的quizArray ArrayList始终为空,因为数据尚未完成加载。

基本上,您正在尝试从异步的API同步使用值。那不是一个好主意。您应该按预期异步处理API。

此问题的快速解决方案是在回调内使用ArrayList only 的值。如果您想在外部使用它,建议您从此 post 中查看anwser的最后一部分,其中已经解释了如何使用自定义回调来完成它。

答案 1 :(得分:0)

正如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")

    }

}