尝试在Kotlin中调用空对象引用的接口方法

3pvhb19x  于 2023-02-13  发布在  Kotlin
关注(0)|答案(1)|浏览(145)

实现viewmodels后jetpack组成应用程序,当我运行该应用程序时,它显示一个错误:-

试图对空对象引用java.lang调用接口方法“boolean java.util.Set.contains(java.lang.Object)”。尝试调用接口方法“boolean java.util.Set.contains(java.lang.Object)”,该方法位于com.example.android.ui.游戏视图模型中的空对象引用上。pickRandomWordAndShuffle(游戏视图模型.kt:21)位于com. example. android. ui.游戏视图模型中。(游戏视图模型.kt:10)

下面是我代码:-

import androidx.lifecycle.ViewModel
import com.example.android.unscramble.data.allWords
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class GameViewModel : ViewModel() {
    private val _uiState =
        MutableStateFlow(GameUiState(currentScrambledWord = pickRandomWordAndShuffle()))
    val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()

    private var _count = 0
    val count: Int
        get() = _count

    private lateinit var currentWord: String
    private var usedWords: MutableSet<String> = mutableSetOf()

    private fun shuffleCurrentWord(word: String): String {
        val tempWord = word.toCharArray()
        // Scramble the word
        tempWord.shuffle()
        while (String(tempWord) == word) {
            tempWord.shuffle()
        }
        return String(tempWord)
    }

    private fun pickRandomWordAndShuffle(): String {
        // Continue picking up a new random word until you get one that hasn't been used before
        currentWord = allWords.random()
        if (usedWords.contains(currentWord)) {
            return pickRandomWordAndShuffle()
        } else {
            usedWords.add(currentWord)
            return shuffleCurrentWord(currentWord)
        }
    }

    private fun resetGame() {
        usedWords.clear()
        _uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle())
    }
    init {
        resetGame()
    }
}

它没有显示任何编译时错误。我不知道该怎么办。

brgchamk

brgchamk1#

在初始化usedWords之前初始化_uiState,这在初始化usedWords之前调用pickRandomWordAndShuffle(),所以在创建的GameViewModel示例中它仍然是null
如果将usedWords的声明移到_uiState之上,它应该可以工作。
然而:在一个示例完全初始化之前调用成员函数通常是个坏主意,正因为如此。
您可以将_uiStateuiState设置为 lazy,这样会更安全。

// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0

private val _uiState by lazy {
    MutableStateFlow(GameUiState(currentScrambledWord = pickRandomWordAndShuffle()))
}
val uiState: StateFlow<GameUiState> by lazy { _uiState.asStateFlow() }

它将等待,直到有东西使用uiState(查看代码只在外部发生,因此可以保证在GameViewModel完全初始化之前不会初始化代码。

相关问题