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 })
}
}
}
여기서 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 })
}
}
}
위의 예제를 가져온 이유는 위의 코드의 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을 위해 사용한다.
MutableState을 by키워드와 함께 쓰게 되면 textState에 getValue와 setValue에 대한 위임(Delegation)이 일어난다. 여기서 주의할 점은 하나의 값에서 setValue또한 일어나야 하기 때문에 val이 아닌 var을 써야한다는 점이다.
var textState by mutableStateOf("")
*만약 오류가 나면 아래 접은글을 보자!
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 })
}
}
}