2

My problem is that i change the uiState but the effect is not there

class BoardViewModel : ViewModel() {
    private var board = mutableListOf<MutableList<Piece?>>()
    private val _uiState = MutableStateFlow(BoardUiState(board.toList()))
    val uiState: StateFlow<BoardUiState> = _uiState.asStateFlow()
    private var selectedPos: Pair<Int, Int>? = null

    init{
        reset()
    }

    private fun reset(){
        board = mutableListOf()
        // this that are not required 
        _uiState.value = BoardUiState(board)
    }

    fun onCellClicked(r: Int, c: Int){
        if(selectedPos != null) {
            move(selectedPos!!.first, selectedPos!!.second, r, c) // i verified this is executed
            selectedPos = null
        }
        else if(board[r][c] != null){
            selectedPos = r to c
        }
    }

    private fun move(sr: Int, sc: Int, dr: Int, dc: Int){
        val temp = board[sr][sc]
        board[sr][sc] = null
        board[dr][dc] = temp
        _uiState.update { currentState ->
            currentState.copy(board = board.toList()) // here im updating the state

             // PROBLEM HERE EVEN WHEN THE BOARD IS CHANGED THE EFFECT IS NOT THERE ON COMPOSITION
        }
    }
}

I verified that the problem is not in other parts of the program, i added dummy int variable to state and changed it in the move function, this time the change happened.

The problem is that change to board is not being detected.

Thanks in advance!

Vigneswar
  • 33
  • 1
  • 4

2 Answers2

2

MutableStateFlow uses structural equality comparison == whenever you update it's value (same goes for mutableStateOf by default), the update will never happen as the structure of the new list is the same as the old (mutated) one, the toList extension function will create a new list with the same elements.

docs:

https://kotlinlang.org/docs/equality.html

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/

Aiden
  • 121
  • 1
  • 2
  • thank you, the problem was that every time the contents of the board were same mutableLists so i added this to my code ``` private fun getBoard(): List>{ val temp = mutableListOf>() for(row in board){ temp.add(row.toList()) } return temp.toList() } ``` and now it worked – Vigneswar Apr 14 '23 at 04:59
0

This happens because method toList() does not creates new object.

Replace this:

currentState.copy(board = board.toList())

Rith this:

currentState.copy(board = listOf(board))

Here is small sample in kotlin playground. You can run this code snippet and you will see, that the result is different for methods toList() and listOf()

tasjapr
  • 632
  • 4
  • 13