Java.lang.IllegalStateException: чтение состояния, созданного после того, как был сделан снимок, или в снимке, который еще не был применен

Я работаю над очень простой игрой-змейкой, используя Kotlin и Jetpack Compose. Чтобы сделать его более эффективным, я подумал об использовании сопрограмм, но постоянно получаю вышеупомянутую ошибку.

Полная версия проекта доступна по адресу: https://github.com/tauqirnizami/SnakeGame

Модель просмотра — это:

class DifficultSnakeViewModel : ViewModel() {
    /*Pair(length/y-coordinate, width/x-coordinate)*/
    var coordinates = mutableStateListOf(Pair(31, 14), Pair(32, 14), Pair(33, 14))
        private set

    private var gameGoing by mutableStateOf(true)

    var extraWallsCoordinates: List<Pair<Int, Int>>

    init {
        foodCoordinates = Pair(10, 9)
        score = 0L
        directions = mutableStateListOf(0) //Using a list instead of a single int to keep track when user changes directions too quickly while the viewModel is on delay (the one for speed controlling). Eg., if user enter up and suddenly left as well, the game earlier used to only register the latter command. Using a mutable list  would keep track of all the given commands that currently hasn't been acted on.
        giantFoodCoordinates = null
        giantFoodCounter = 1

        extraWallsCoordinates = walls()

        viewModelScope.launch(Dispatchers.Default) {
            delay(1000L) //This is to let the viewModel to setup properly before being used. I was getting error due to usage of state variable (probably "coordinates") before waiting for the viewModel to be able to initialize properly first
            while (gameGoing) {
                delay(if (score < 250) 500 - (score *2) else if (score<500) 1 else 0) //This controls the snake speed
                coordinatesUpdation() //This is used to update the snake's coordinates according to the direction, i.e., user input.
            }
        }
    }
//other code
}

Как видите, в простом и среднем режиме игры использования простой задержки (550L) было достаточно, чтобы избежать ошибки, но на сложном уровне это не работает, даже если я увеличил продолжительность задержки с 550 до 1000. или даже 3000 миллис.

Мой составной файл:

@Composable
fun DifficultDisplayGrid(
    modifier: Modifier,
    snakeViewModel: DifficultSnakeViewModel
) {
    val colors = difficultGenerateColorGrid(coordinates = snakeViewModel.coordinates, walls = snakeViewModel.extraWallsCoordinates) //This function returns a list of colours according to snake, food, etc's coordinates, which would be used to display the grid
    Column {
        ColorGrid(colors = colors, modifier = modifier) //snake game grid
        Text(text = "Score = $score")
    }

}

@Composable
fun DifficultScreen(
    modifier: Modifier = Modifier,
    snakeViewModel: DifficultSnakeViewModel = DifficultSnakeViewModel()
) {
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier
    ) {
        DifficultDisplayGrid(modifier, snakeViewModel = snakeViewModel)

        Row(
            modifier = Modifier,
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center
        ) {
            Button(onClick = { directions.add(2) }) {
                Icon(imageVector = Icons.Filled.KeyboardArrowLeft, contentDescription = "Left")
            }
            Column {
                Button(onClick = { directions.add(0) }) {
                    Icon(imageVector = Icons.Filled.KeyboardArrowUp, contentDescription = "Up")
                }
                Spacer(modifier = Modifier.height(13.dp))
                Button(onClick = { directions.add(1) }) {
                    Icon(imageVector = Icons.Filled.KeyboardArrowDown, contentDescription = "Down")
                }
            }
            Button(onClick = { directions.add(3) }) {
                Icon(imageVector = Icons.Filled.KeyboardArrowRight, contentDescription = "Right")
            }
        }
    }
}
//other code

Я попытался использовать функцию задержки(), Thread.sleep(). Пытался использовать thread.sleep перед строкой viewModelScope.launch, пытался сделать это внутри этой области. Но ничего не работало. От 1000 до 50 000 милли ни одна функция или продолжительность не работают.

Отвечает ли это на ваш вопрос? java.lang.IllegalStateException при использовании State в Android Jetpack Compose

gtxtreme 10.06.2024 16:14
0
1
111
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

попробуй это

viewModelScope.launch(Dispatchers.Main) {
  //  delay(1000L) //This is to let the viewModel to setup properly before being used. I was getting error due to usage of state variable (probably "coordinates") before waiting for the viewModel to be able to initialize properly first
    while (gameGoing) {
        delay(if (score < 250) 500 - (score *2) else if (score<500) 1 else 0) //This controls the snake speed
        coordinatesUpdation()
    }
}

Чтобы узнать больше о Dispachers, вы можете прочитать здесь -> https://developer.android.com/kotlin/coroutines/coroutines-adv?hl=es-419#main-safety

Я столкнулся с той же проблемой при изменении состояния, которое используется в составной функции, вне основного потока. в конце концов я решил проблему, используя основной поток для изменения состояния. в вашем случае, как упоминал @witodev, вы должны использовать:

viewModelScope.launch(Dispatchers.Main) { /* your operation */ }

Другие вопросы по теме