Image
Android Jetpack Compose/Compose State

[Android Compose State] MutableState을 remember과 함께 다루는 다양한 방법 : 구조분해, by 키워드(Delegation) 사용

remember이란

Compose는 State값이 바뀌면 Recomposition(재구성)이 일어난다. 이때 이전 State를 기억해야 하는 경우 remember을 이용해 값을 저장할 수 있다.

 

예를 들어 아래와 같이 remember 없이 textState를 저장할 경우 값이 입력될 때마다 State가 바뀌어 Recomposition이 일어나 textState에 다시 mutableStateOf("")이 세팅되게 된다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val textState = mutableStateOf("")
            TextField(value = textState.value, onValueChange = { textValue -> textState.value = textValue })
        }
    }
}

그림1. remember 없이 사용

 

여기서 remember 키워드를 추가해주면 TextField에 값이 정상 출력되는 것을 볼 수 있다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val textState = remember {
                mutableStateOf("")
            }
            TextField(value = textState.value, onValueChange = { textValue -> textState.value = textValue })
        }
    }
}

그림2. remember과 함께 사용

 

위의 예제를 가져온 이유는 위의 코드의 MutableState부분을 우아하게 바꾸어 보려고 하기 때문이다.

 

MutableState 다루기

MutableState은 총 3가지 방법으로 사용이 가능하다. 위에서는 이 중 단순 remember을 사용해 값을 저장했으므로, 아래에서는 MutableStat

  • 단순 remember 사용
  • 구조분해 사용
  • by 사용 (Delegation 사용)

 

구조 분해 사용

MutableState의 구조분해 구문을 사용해보자.

@Stable
interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

MutableState 내부를 살펴보면 두개의 operator fun 이 있다. 첫번째는 mutableState 내부의 값을 나타내는 component1()이고 둘째는 값이 들어왔을 때 내부의 값을 세팅하는 람다식이다.

 

우리는 이를 다음과 같이 쓸 수 있다.

val (textState, setTextState) = mutableStateOf("")

 

mutableState의 값(textState)과 세팅에 대한 function을 람다식(setTextState)로 따로 받을 수 있다.

 

따라서 코드를 다음과 같이 바꾸면 동작한다.

setContent {
    val (textState, setTextState) = remember { mutableStateOf("") }
    TextField(value = textState, onValueChange = setTextState)
}

최종 코드는 다음과 같다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val (textState, setTextState) = remember { mutableStateOf("") }
            TextField(value = textState, onValueChange = setTextState)
        }
    }
}

 

 

 

by 사용 (Delegation 사용)

MutableState의 getValue와 setValue에 대한 Delegation 또한 사용할 수 있다. 우리는 여기서 androidx.compose.runtime의 getValue와 setValue fun을 Delegation을 위해 사용한다.

그림3. delegation

MutableState을 by키워드와 함께 쓰게 되면 textState에 getValue와 setValue에 대한 위임(Delegation)이 일어난다. 여기서 주의할 점은 하나의 값에서 setValue또한 일어나야 하기 때문에 val이 아닌 var을 써야한다는 점이다.

var textState by mutableStateOf("") 

*만약 오류가 나면 아래 접은글을 보자!

더보기
안드로이드 스튜디오에서 by에 대한 import가 자동으로 안된다. 아래의 두개 import 구문을 위에 추가해주도록 하자.
import androidx.compose.runtime.setValue
import androidx.compose.runtime.getValue

 

따라서 코드를 다음과 같이 바꾸면 동작한다. 

setContent {
    var textState by remember { mutableStateOf("") }
    TextField(value = textState, onValueChange = { textValue -> textState = textValue })
}

 

최종 코드는 다음과 같다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var textState by remember { mutableStateOf("") }
            TextField(value = textState, onValueChange = { textValue -> textState = textValue })
        }
    }
}
반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com