TIL : mutableStateList와 SnapshotStateList

김성환·2024년 7월 22일

Compose의 State를 사용하다 보면 리스트 형태의 State가 필요할 때가 있습니다.

val names by remember {
    mutableStateOf(mutableListOf<String>())
}

Log.d("********", "TestSpace: ${names.size}")
LaunchedEffect(true) {
    names.add("test")
}

이와 같은 형태를 사용할 때 원하는 결과를 얻지 못할 수 있습니다. mutableListOf를 통해 가변적인 리스트를 만들면 일반적으로 값 자체를 바꾸는 것이 아니라 add 같은 함수를 사용해서 값을 추가합니다. 이 경우 값이 직접 바뀌는 것이 아니기 때문에 State가 변경되지 않은 것으로 간주되어 Recompose가 발생하지 않습니다. 따라서 Recompose가 되기 위해 값을 바꿔줄 필요가 있습니다.

var names by remember {
    mutableStateOf(listOf<String>())
}

Log.d("********", "TestSpace: ${names.size}")
LaunchedEffect(true) {
    names = names + "test"
}

이런 식으로 바꿀 수도 있지만, 변경될 때마다 리스트의 새 인스턴스가 생성된다는 단점이 있습니다. 그래서 Android에서는 mutableStateListOf 메서드를 지원하여 SnapshotStateList 형태의 MutableList를 State 형태로 감지할 수 있습니다.

val names = remember {
    mutableStateListOf<String>()
}

Log.d("********", "TestSpace2: ${names.size}")
LaunchedEffect(true) {
    names.add("test")
}

그렇다면 ViewModel의 리스트 형태의 LiveData나 StateFlow를 Compose에서 사용할 수 있게 State로 바꾸는 상황을 생각해봅시다. 이전 글에도 말했다시피 LiveData나 StateFlow를 State 형태로 바꿀 수 있습니다. Immutable한 List를 사용할 때는 큰 변화가 없습니다. List가 바뀌는 상황은 value 자체가 바뀌는 상황이고 리파지토리나 DataSource를 통해 받는 데이터이기 때문에 받는 값으로 매번 value가 바뀝니다. 그렇지만 간단하게 mutable로 사용하기 위해서는 굳이 이 경우에 LiveData나 StateFlow를 이용할 필요 없이 mutableStateListOf를 사용해도 됩니다. LiveData나 StateFlow를 바꿀 때는 State 형태로 바뀌기 때문에 위에서 언급한 것처럼 변경을 감지하지 못할 것입니다.

0개의 댓글