Попытка вызвать метод интерфейса для нулевой ссылки на объект в kotlin

После внедрения моделей просмотра в приложение для создания реактивного ранца, когда я запускаю приложение, оно показывает ошибку: -

Попытка вызвать метод интерфейса 'boolean java.util.Set.contains(java.lang.Object)' для нулевой ссылки на объект java.lang.NullPointerException: попытка вызвать метод интерфейса 'boolean java.util.Set.contains(java.lang.Object)» в ссылке на нулевой объект в com.example.android.ui.GameViewModel.pickRandomWordAndShuffle(GameViewModel.kt:21) в com.example.android.ui.GameViewModel.(GameViewModel.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()
    }
}

Он не показывает никаких ошибок времени компиляции. Я не знаю, что мне делать.

1 ответ

Вы инициализируете перед инициализацией . Это вызываетpickRandomWordAndShuffle()до того, как был инициализирован, поэтому он все ещеnullв создаваемом экземпляре.

Если вы переместите декларациюusedWordsвыше должно работать.

ОДНАКО: как правило, плохая идея вызывать функции-члены до того, как экземпляр будет полностью инициализирован, именно по этой причине.

Вы могли бы сделать_uiStateи 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был полностью инициализирован.