【问题标题】:Cannot fill a MutableLiveData of type ArrayList, outcome is always null无法填充 ArrayList 类型的 MutableLiveData,结果始终为空
【发布时间】:2021-07-06 20:33:08
【问题描述】:

我正在做一个问答游戏,我想将一些 id 存储在 MutableLiveData-arraylist 中。因此,我创建了一个函数来循环我在数据库中的所有文档并将每个 ID 添加到数组列表中。但结果始终为空。我看不出哪里出错了?

我正在使用 MVVM 结构

游戏视图模型:

class GameViewModel : ViewModel() {

// database instance
val db = FirebaseFirestore.getInstance()

// the current category
private val _category = MutableLiveData<String>()
val category: LiveData<String>
    get() = _category

// the list of questionIds of the selected category
private val _questionIdsArray = MutableLiveData<ArrayList<Long>>()
val questionIdsArray: LiveData<ArrayList<Long>>
    get() = _questionIdsArray

// the current question
private val _question = MutableLiveData<String>()
val question: LiveData<String>
    get() = _question


/**
 * Set Current Category
 */
fun SetCategory (categoryName: String){
    _category.value = categoryName
}

/**
 * Get the list of QuestionIds
 */
fun GetListQuestionIds() {
    db.collection("questions")
        .whereEqualTo("category", "$_category")
        .get()
        .addOnSuccessListener { documents ->
            for (document in documents) {
                _questionIdsArray.value?.add(document.data["questionid"] as Long)
                Log.d("GetSize","${_questionIdsArray.value?.size}")
            }
            Log.d("GetSize2","${_questionIdsArray.value?.size}")
        }
        .addOnFailureListener { exception ->
            Log.w("errorforloop", "Error getting documents: ", exception)
        }
}
/**
 * Get a Question
 */
fun GetQuizQuestion() {
    Log.d("retro","${_questionIdsArray.value?.size}")
    db.collection("questions")
        .whereEqualTo("category", "$_category")
        .whereEqualTo("questionid", "${_questionIdsArray.value?.get(0)}")
        .get()
        .addOnSuccessListener { documents ->
            for (document in documents) {
                _question.value = document.data["question"].toString()
            }
        }
        .addOnFailureListener { exception ->
            Log.w("err", "Error getting documents: ", exception)
        }
}

游戏片段:

class GameFragment : Fragment() {

private lateinit var viewModel: GameViewModel

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val binding = FragmentGameBinding.inflate(inflater)

    // Get the viewModel
    viewModel = ViewModelProvider(this).get(GameViewModel::class.java)
    binding.lifecycleOwner = this

    // Set the viewModel for DataBinding - this allows the bound layout access to all of the data in the VieWModel
    binding.gameviewModel = viewModel

    //arguments passed
    val selectedCategory = arguments?.getString("selectedCategory")!!

    //set current category so that the viewModel can use it
    viewModel.SetCategory(selectedCategory)

    viewModel.GetListQuestionIds()
    viewModel.GetQuizQuestion()

    return binding.root
}

如果有人能启发我...

【问题讨论】:

    标签: firebase android-studio kotlin android-livedata


    【解决方案1】:

    您的问题

    您没有初始化数组。这是你的代码:

    // the list of questionIds of the selected category
    private val _questionIdsArray = MutableLiveData<ArrayList<Long>>()
    val questionIdsArray: LiveData<ArrayList<Long>>
        get() = _questionIdsArray
    

    这声明了一个ArrayList&lt;Long&gt; 类型的MutableLiveData,但没有初始化它,所以它的value 默认为null

    在你的 for 循环中,你有条件地添加项目:

    _questionIdsArray.value?.add(document.data["questionid"] as Long)
    

    当然,value 从未初始化,所以它为 null,所以 add 是无操作(什么都不做)。

    解决方案

    只要确保在某个时候初始化实时数据对象即可。

    您可以在声明中内联执行此操作:

    // the list of questionIds of the selected category
    private val _questionIdsArray = MutableLiveData<ArrayList<Long>>(arrayListOf())
    val questionIdsArray: LiveData<ArrayList<Long>>
        get() = _questionIdsArray
    

    或者在您尝试填充列表的过程中:

        .addOnSuccessListener { documents ->
            val idsArray = arrayListOf<Long>() // Non-null list to add to
            for (document in documents) {
                idsArray.add(document.data["questionid"] as Long)
                Log.d("GetSize","${idsArray.size}")
            }
    
            _questionIdsArray.value = idsArray // Now set live data with a valid list
            Log.d("GetSize2","${_questionIdsArray.value?.size}")
        }
    

    【讨论】:

    • 感谢您的回答,但我仍然收到 IndexOutOfBoundsException:索引:0,大小:0,我尝试了两种解决方案,但我得到了相同的异常
    • 您正在调用_questionIdsArray.value?.get(0),这是列表的第一个元素 - 但您的列表为空,因此没有第一个元素。你需要检查这种可能性并处理它
    • 我想知道在一个类中分离firebase代码是否正确?将在视图模型中使用。
    猜你喜欢
    • 2017-09-30
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多