본문 바로가기

개발일지

[Kotlin] Compose 입문 #5 - State 심화

**class StateViewModel: ViewModel() {
    private val _value = mutableStateOf("Hello World")
    val value: State<String> = _value
}**

mutableState → [var] 읽기, 쓰기 모두 가능

operator fun component가 있는데 getter, setter의 역할

 

State<String> → [val] 읽기만 가능

 

 

fun HomeScreen(viewModel: StateViewModel = androidx.lifecycle.viewmodel.compose.viewModel()) {
    var text1: MutableState<String> = remember {
        mutableStateOf("Hello World")
    }

    // 구조분해
    var (text: String, setText: (String) -> Unit) = remember {
        mutableStateOf("Hello World")
    }

해당 코드에서,

text1 을 하나만 썼을 땐 MutableState 변수가 된다

 

 

구조분해한 경우

text는 String 변수, setText는 String을 입력받아서 Unit을 반환하는 함수

 

 

즉, TextField에서 다음과 같이 사용할 수 있다

TextField(value = text, onValueChange = setText)

onValueChange가 불러와지면서 setText가 Setter의 역할

 

 

 

이때, 텍스트를 변경하면 화면이 다시 그려지는데

이것을 리컴포지션 이라고 한다

→ 글자를 수정할 때마다 리컴포지션

 

 

 

다른 방법 → by 사용하기

by에는 getValue와 setValue가 구현되어 있다

import 뜯어보기

import androidx.compose.runtime.*

runtime.* 으로 모두 임포트 한 것처럼 되어있지만

자동으로 임포트 되지 않는 경우도 있다

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

그럴 땐 직접 이렇게 임포트 해주자

 

그래서 by를 왜 쓰는데 !

val text1: MutableState<String> = remember {
        mutableStateOf("Hello World")
    }

var text2: String by remember {
        mutableStateOf("Hello World")
    }

by를 쓰면 text는 String변수가 되고, 구조분해 했을 때의 text와 동일한 기능

 

데이터 변경은 다음과 같이

**Button(onClick = {
            text2 = "변경"
            print(text2)
        })**

간단하게 text2를 String변수처럼 사용할 수 있다!

하지만 실제로 데이터 변경은 mutableStateOf 안에서 이루어진다는 점

 

 

Button(onClick = {
            text1.value = "변경"
            print(text1.value)
            text2 = "변경"
            print(text2)
            setText("변경")
        })

text1을 변경하려면 text1.value 처럼 value를 붙여줘야 한다는 점

text를 변경하려면 setText를 변경해야 한다

 

viewModel 객체 변경하기

class StateViewModel: ViewModel() {
    private val _value: MutableState<String> = mutableStateOf("Hello World")
    val value: State<String> = _value
}

value가 val 변수로, 읽기형태 → 수정이 불가하다!

따라서, 다음과 같이 데이터를 변경하는 함수 코드를 작성하자

class StateViewModel: ViewModel() {
    private val _value: MutableState<String> = mutableStateOf("Hello World")
    val value: State<String> = _value

    // val 형태의 value를 변경하는 함수
    fun changeValue(value: String) {
        _value.value = value
    }
}

버튼 클릭시 viewModel의 값을 수정하는 코드를 추가한다

Button(onClick = {
            text1.value = "변경"
            print(text1.value)
            text2 = "변경"
            print(text2)
            setText("변경")

            // viewModel 데이터 변경
            viewModel.changeValue("변경")
        })

 

 

 

라이브데이터

우선 gradle 추가

// LiveData
    implementation "androidx.compose.runtime:runtime-livedata:1.4.3"

그리고 ViewModel Class 에서 liveData 선언

class StateViewModel: ViewModel() {
    private val _value: MutableState<String> = mutableStateOf("Hello World")
    val value: State<String> = _value

    // 기존의 LiveData 사용하기
    // 외부에서는 수정이 안되게
    private val _liveData = MutableLiveData<String>()
    val liveData: LiveData<String> = _liveData

컴포저블에 선언

// 라이브데이터 활용
    val text3: State<String> = viewModel.liveData.observeAsState("Hello World")