按钮 onClick 继续替换 mutableStateList 中的值

Button onClick keep replacing values in mutableStateList

我正在尝试显示一个 4x4 网格,其值会根据用户输入而变化。为实现这一点,我创建了 mutableStateListOf,我在 ViewModel 中使用它来保存配置更改。但是,当我尝试使用按钮 onClick 替换该特定列表中的值时,它会一直这样做,直到应用程序崩溃。我不明白为什么单击按钮一次后 onReplaceGridContent 会循环。目前,我的代码如下所示:

视图模型:

class GameViewModel : ViewModel(){

    var gameGridContent = mutableStateListOf<Int>()
        private set // Restrict writes to this state object to private setter only inside view model

    fun replaceGridContent(int: Int, index: Int){
        gameGridContent[index] = int
    }

    fun removeGridContent(index: Int){
        gameGridContent[index] = -1
    }

    fun initialize(){
        for(i in 0..15){
            gameGridContent.add(-1)
        }

        val firstEmptyGridTile = GameUtils.getRandomTilePosition(gameGridContent)
        val firstGridNumber = GameUtils.getRandomTileNumber()

        gameGridContent[firstEmptyGridTile] = firstGridNumber
    }
}

按钮:

Button(
  onClick = { 
      onReplaceGridContent(GameUtils.getRandomTileNumber(),GameUtils.getRandomTilePosition(gameGridContent))},
      colors = Color.DarkGray
    ){
      Text(text = "Add number to tile")
    }

Activity 可组合:

@Composable
fun gameScreen(gameViewModel: GameViewModel){
    gameViewModel.initialize()
    MainStage(
        gameGridContent = gameViewModel.gameGridContent,
        onReplaceGridContent = gameViewModel::replaceGridContent,
        onRemoveGridContent = gameViewModel::removeGridContent
    )
}

你的 initialize 实际上 运行 每次重组 gameScreen:

  1. 您单击一个图块 - 状态变化导致重新组合。
  2. initializa 被调用并再次改变状态导致重组。
  3. 步骤 2 一次又一次地发生。

您应该改为在其构造函数中初始化您的视图模型(或使用布尔标志强制执行一次 tim 初始化)以使其仅执行一次。

只需将其更改为构造函数:

class GameViewModel : ViewModel(){

    var gameGridContent = mutableStateListOf<Int>()
        private set // Restrict writes to this state object to private setter only inside view model

    fun replaceGridContent(int: Int, index: Int){
        gameGridContent[index] = int
    }

    fun removeGridContent(index: Int){
        gameGridContent[index] = -1
    }

    init {
        for(i in 0..15){
            gameGridContent.add(-1)
        }

        val firstEmptyGridTile = GameUtils.getRandomTilePosition(gameGridContent)
        val firstGridNumber = GameUtils.getRandomTileNumber()

        gameGridContent[firstEmptyGridTile] = firstGridNumber
    }
}

现在您不需要在可组合项中调用初始化:

@Composable
fun gameScreen(gameViewModel: GameViewModel){
    MainStage(
        gameGridContent = gameViewModel.gameGridContent,
        onReplaceGridContent = gameViewModel::replaceGridContent,
        onRemoveGridContent = gameViewModel::removeGridContent
    )
}