아래 영상을 보고 정리한 게시글입니다.
https://www.youtube.com/watch?v=JuIw_SbSpRU&list=PLxTmPHxRH3VV8lJq8WSlBAhmV52O2Lu7n&index=8
Recomposable
아래와 같이 작성하면
버튼을 눌러도 Text의 내용이 변하지 않음
@SuppressLint("UnrememberedMutableState")
@Preview(showBackground = true)
@Composable
fun TestView() {
val data = mutableStateOf("Hello")
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = data.value,
fontSize = 30.sp,
)
Button(onClick = {
data.value = "World"
}) {
Text(text = "변경")
}
}
}
composable 안에서 state가 바뀌면 recomposable 해야함
그래서 다시 TestView()의 처음부터 실행하는데 data 값이 "hello"로 초기화돼서
여전히 "hello"로 보이는 것임
remember
기존 state를 유지하기 위해서 remember를 사용함
그러면 hello -> world로 잘 변한다
@Preview(showBackground = true)
@Composable
fun TestView() {
val data = remember {
mutableStateOf("Hello")
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = data.value,
fontSize = 30.sp,
)
Button(onClick = {
data.value = "World"
}) {
Text(text = "변경")
}
}
}
ViewModel
activity와 lifecycle을 동일하게 가져가기 때문에
remember를 신경쓰지 않아도 됨
+) 화면 회전과 같이 screen을 다시 만드는 과정에서도 viewModel이 state를 가지고 있기 때문에 값을 안 잃고 잘 들고있음
(위의 방식은 "world"에서 화면을 돌리면 "hello"로 바껴서 나온다)
MainViewModel 작성
class MainViewModel : ViewModel() {
val data = mutableStateOf("Hello")
}
방법 1. 기존에 사용하던 방식
액티비티 코드 안에 아래와 같이 작성
private val viewModel by viewModels<MainViewModel>()
그리고 viewModel.data로 안의 내부 변수 접근
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposePracticeTheme {
// A surface container using the 'background' color from the theme
Surface(
color = MaterialTheme.colors.background
) {
TestView(viewModel)
}
}
}
}
}
@Composable
fun TestView(viewModel: MainViewModel) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = viewModel.data.value,
fontSize = 30.sp,
)
Button(onClick = {
viewModel.data.value = "World"
}) {
Text(text = "변경")
}
}
}
방법 2. Composable 안에서 사용하는 방식
module 수준의 build.gradle 안에 아래를 적어줌
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-rc01'
이러면 Composable 안에서 ViewModel을 선언할 수 있음
@Composable
fun TestView() {
val viewModel = viewModel<MainViewModel>()
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = viewModel.data.value,
fontSize = 30.sp,
)
Button(onClick = {
viewModel.data.value = "World"
}) {
Text(text = "변경")
}
}
}
ViewModel을 쓰는 이유
View에서 data를 직접 다루는건 지양
(textView에 들어갈 data를 바꾼다던가 등등)
이거를 ViewModel에서 한다
코드를 좀 더 viewModel 스럽게 바꾸면
- viewModel 안의 변수를 private으로 바꿔줌
- 외부한테는 읽기 전용으로 제공함
- 수정하기 위해서 method를 제공함
class MainViewModel : ViewModel() {
private val _data = mutableStateOf("Hello")
val data: State<String> = _data
fun changeValue(value: String) {
_data.value = value
}
}
@Composable
fun TestView() {
val viewModel = viewModel<MainViewModel>()
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = viewModel.data.value,
fontSize = 30.sp,
)
Button(onClick = {
viewModel.changeValue("World")
}) {
Text(text = "변경")
}
}
}
결과물
'Jetpack Compose' 카테고리의 다른 글
[Jetpack Compose] 12. by 위임 (0) | 2023.09.21 |
---|---|
[Jetpack Compose] 10. Navigation - 값 전달하기 (0) | 2023.09.20 |
[Jetpack Compose] 9. Navigation - 화면 전환 (0) | 2023.09.20 |
[Jetpack Compose] 8. SnackBar, 코루틴 (0) | 2023.09.20 |
[Jetpack Compose] 7. TextField, 구조 분해 (1) | 2023.09.20 |