package com.example.modern_android_state_20230127
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.setValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.modern_android_state_20230127.ui.theme.Modern_Android_State_20230127Theme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HomeScreen()
}
}
}
@Composable
fun HomeScreen(viewModel: MainViewModel = viewModel()) {
// state -> 상태를 저장
// text1 타입이 MutableState
var text1 = remember {
mutableStateOf("Hello World")
}
// text2 타입이 String
// by는 코틀린의 델리게이트 프로퍼티 기능을 활용해서 setter getter를 재정의 해놓음
var text2 by remember {
mutableStateOf("Hello World")
}
// text 타입이 String
val (text, setText) = remember {
mutableStateOf("Hello World")
}
// 기존 LiveData를 State로 변환
val text3: State<String> = viewModel.liveData.observeAsState("Hello World")
// -> Compose는 State기반으로 동작한다
Column() {
Text(text = "Hello World")
Button(onClick = {
text1.value = "변경"
text2 = "변경"
print(text1.value)
print(text2)
// text = "변경"
setText("변경")
// viewModel.value.value = "변경"
viewModel.changeValue("변경")
}) {
Text(text = "클릭")
}
TextField(value = text, onValueChange = setText)
}
}
class MainViewModel : ViewModel() {
private val _value = mutableStateOf("Hello World")
val value: State<String> = _value
private val _liveData = MutableLiveData<String>()
val liveData: LiveData<String> = _liveData
fun changeValue(value: String){
_value.value = value
}
}
remember
는 객체를 컴포지션에 저장하고, remember
를 호출한 컴포저블이 컴포지션에서 삭제되면 그 객체를 잊습니다. [mutableStateOf]는 관찰 가능한 MutableState<T>를 생성하는데, 이는 런타임 시 Compose에 통합되는 관찰 가능한 유형입니다.interface MutableState<T> : State<T> {
override var value: T
operator fun component1(): T
operator fun component2(): (T) -> Unit
}
value
가 변경되면 value
를 읽는 구성 가능한 함수의 리컴포지션이 예약된다. 컴포저블에서 MutableState
객체를 선언하는 데는 세 가지 방법이 있다.val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
이러한 선언은 동일한 것이며 서로 다른 용도의 상태를 사용하기 위한 구문 슈가로 제공됩니다. 작성 중인 컴포저블에서 가장 읽기 쉬운 코드를 생성하는 선언을 선택해야 합니다.
by
위임 구문에는 다음 가져오기가 필요합니다.
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
기억된 값을 다른 컴포저블의 매개변수로 사용하거나 문의 로직으로 사용하여 표시할 컴포저블을 변경할 수 있습니다. 예를 들어 이름이 비어 있는 경우 인사말을 표시하지 않으려면 if
문에 상태를 사용합니다.
@Composable
fun HelloContent() {
Column(modifier = Modifier.padding(16.dp)) {
var name by remember { mutableStateOf("") }
if (name.isNotEmpty()) {
Text(
text = "Hello, $name!",
modifier = Modifier.padding(bottom = 8.dp),
style = MaterialTheme.typography.h5
)
}
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
}
}
remember
가 재구성 과정 전체에서 상태를 유지하는 데 도움은 되지만 구성 변경 전반에서는 상태가 유지되지 않는다. 이 경우에는 rememberSaveable
을 사용해야 한다. rememberSaveable
은 Bundle
에 저장할 수 있는 모든 값을 자동으로 저장합니다. 다른 값의 경우에는 맞춤 Saver 객체를 전달할 수 있다.