컴포즈에서의 ViewModel
버튼을 클릭하였을 때 원래 있던 텍스트가 다른 텍스트로 변경되는 프로그램을 구현하였을 때
생명주기를 고려하지 않는다면 다음과 같이 구현할 수 있다.
// val data = remember{mutableStateOf("Hello")}
Button(onClick = {
// data.value = "World" //눌러도 변경이 안됨.
//변경이 되면 컴포즈가 다시 리셋이되어 hello가 계속 나옴
//따라서 리멤버 사용
만일 remember를 사용하지 않는다면 눌러도 변경이 안되는 것을 확인할 수 있다.
왜냐하면 변경이 되어도, 다시 컴포지션이 발생하여 리셋이 되어 원래 있던 Hello가 계속 나오게 된다.
이를 해결하기 위해 이전에 있던 상태를 기억하기 위해 위의 코드처럼 remember를 사용해서 데이터를 변경하게끔 할 수도 있다.
또한 이 때 ViewModel을 사용할 수도 있다.
class MainViewModel : ViewModel(){
private val _data = mutableStateOf("Hello")
val data : State<String> = _data
fun changeValue(){
_data.value = "World"
}
}
위와 같이 ViewModel을 생성하여 data의 값을 바꿀 수 있다.
setContent {
// val data = remember{mutableStateOf("Hello")}
//있던 스테이트를 기억하기 위해 : 이런식으로 코드 작성을 했음
val viewModel = viewModel<MainViewModel>()
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
){
Text(
viewModel.data.value,
fontSize = 30.sp,
)
Button(onClick = {
// viewModel.data.value = "World" //눌러도 변경이 안됨.
//변경이 되면 컴포즈가 다시 리셋이되어 hello가 계속 나옴
//따라서 리멤버 사용
viewModel.changeValue()
}){
Text("변경")
}
}
}
이렇게 viewModel을 생성해주고, viewModel.changeValue()를 통해 값을 바꿀 수 있다.
ViewModel은 LiveData와 주로 함께 사용했던터라 사용할 때 불편함은 없었다.
State
공식문서에 따르면 Compose는 앞서 설명했듯이 선언적이므로 유일한 방법은 새 인수로 동일한 컴포저블을 호출하는 것이다.
상태가 업데이트될 때 마다 재구성이 실행되어 TextField같은 것들은 자동으로 업데이트 되지 않아 입력을 아무리해도
입력이 되지 않는 것처럼 보인다.
따라서 이 때는 새 상태에 따라 업데이트 되려면 새 상태를 명시적으로 알려주어야한다. 이와 같이 나와있다.
해석해보자면, Composable은 상태에 따라 ui를 구성하고 함수이기 때문에 상태 값을 지역변수로 설정하면 재구성이 될 때마다 저장된 상태 값이 소실된다. 따라서 계속 유지해야하는데 이를 지원하는 것이 remember이다.
그리고 이 때 상태를 저장하고 변경되었을 때 재구성을 하기위해 관찰가능한 객체 MutableState를 사용할 수 있다.
val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
mutableState 객체를 선언하는 방법은 위와같이 세 가지가 있다.
먼저 첫 번째 방법은 맨 위의 코드처럼 하는 간단한 방법이다.
두 번째 방법은 by키워드를 사용하면 된다. 이 때 변경과 읽어오기 위한 getValue와 setValue를 import해주어야한다.
마지막 방법은 다음과 같이 코틀린 구조분해를 이용한 방법이다.
val (text, setText) = remember {
mutableStateOf("Hello")
}
TextField(value = text, onValueChange = setText)
이렇게 TextField를 사용할 때 많이 사용된다.
현재에 있는 값이 먼저 출력이 되고, 값이 변하면 onValueChange가 일어나면서 setText가 실행된다.
따라서 setText를 통해 String인 text가 변경이되고, 바로 ui에 반영되면서 계속해서 컴포지션이 발생한다.
이렇게 Compose는 State기반으로 항상 화면이 그려지기 때문에 State에 대한 개념이 중요하다!
아직 잘 다루는 정도는 아니지만 더 깊게 공부하여 완벽히 이해해야겠다!!
ViewModel
GitHub - SsongSik/Jetpack_Compose: Creating apps using Jetpack Compose
Creating apps using Jetpack Compose. Contribute to SsongSik/Jetpack_Compose development by creating an account on GitHub.
github.com
State
GitHub - SsongSik/Jetpack_Compose: Creating apps using Jetpack Compose
Creating apps using Jetpack Compose. Contribute to SsongSik/Jetpack_Compose development by creating an account on GitHub.
github.com
'Android > Compose' 카테고리의 다른 글
[Compose]스톱워치 (0) | 2022.09.29 |
---|---|
[Compose]비만도 계산기 (0) | 2022.09.24 |
[Compose] Navigation (0) | 2022.09.22 |
[Compose] TextField, Scaffold, SnackBar (0) | 2022.09.21 |
[Compose] Image, Card, State (0) | 2022.09.15 |