java.lang.IllegalStateException:读取在拍摄快照后或尚未应用的快照中创建的状态

问题描述 投票:0回答:1

我正在使用 kotlin 和 jetpack compose 开发一个非常基本的贪吃蛇游戏。为了提高效率,我想到了使用协程,但我不断收到上述错误。

完整项目共享于:https://github.com/tauqirnizami/SnakeGame

ViewModel 是:

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

我尝试使用delay()函数,Thread.sleep()。尝试在 viewModelScope .launch 行之前使用 thread.sleep ,尝试在此范围内执行此操作。但没有任何效果。从 1000 毫利斯到 50000 毫利斯,似乎没有任何功能或没有持续时间。

android kotlin mvvm android-jetpack-compose kotlin-coroutines
1个回答
0
投票

试试这个

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()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.