Compose 기초 - State 심화

황준하·2023년 1월 28일
0

Android-Kotlin-Compose

목록 보기
8/9
  • 전체 코드
    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
        }
    }
  • 상태 및 구성 Compose는 선언적이므로 Compose를 업데이트하는 유일한 방법은 새 인수로 동일한 컴포저블을 호출하는 것이다.
    여기서 인수는 UI 상태를 표현한다. 상태가 업데이트될 때마다 재구성이 실행된다. 따라서 TextField와 같은 항복은 명령형 XML 기반 뷰에서처럼 자동으로 업데티트 되지않고 컴포저블이 새 상태에 따라 업데이트되려면 새 상태를 명시적으로 알려야한다.
  • 컴포저블의 상태 remember API를 사용하여 메모리에 객체를 저장할 수 있다.
    remember에 의해 계산된 값은 초기 컴포지션 중에 컴포지션에 저장되고 저장된 값은 리컴포지션 중에 반환된다.
    rememer는 변경 가능한 객체뿐만 아니라 변경할 수 없는 객체를 저장하는 데 사용할 수 있다. 참고: 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 객체를 전달할 수 있다.


틀린 부분 지적은 언제나 환영해요🤗
profile
Xlnt한 날까지 노력하는 개발자

0개의 댓글