Compose - State Hoisting

FLUORITE·2025년 1월 18일

안드로이드

목록 보기
12/32

package kr.co.fastcampus.part1.chapter4_13

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.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kr.co.fastcampus.part1.chapter4_13.ui.theme.StateTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            StateTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
                ) {
                    PyeongToSquareMeter()
                }
            }
        }
    }
}

@Composable
fun PyeongToSquareMeter() {
    var pyeong by rememberSaveable{ // 저장 공간의 한계가 있기 때문에 remembeSaveable을 사용하는 것은 좋지 않다.
        mutableStateOf("23")
    }
    var squaremeter by rememberSaveable {
        mutableStateOf((23 * 3.306).toString())
    } // 이러한 자료를 뷰모델에 옮길 수 있다.
    // remember는 내부에서 호출하므로 remember와 rememberSaveable만 가장 근본적인 메소드라고 할 수 있고 나머지는 유틸리티다.


    // 단계 1: remember를 이용해 상태를 만들고 평 값을 입력하면
    // 제곱미터가 출력되도록 화면을 구성하시오.
    // 평을 제곱미터로 바꾸기 위해서는 3.306을 곱하면 됩니다.
//    Column(modifier = Modifier.padding(16.dp)) {
//        OutlinedTextField(
//            value = pyeong,
//            onValueChange = {
//                if (it.isEmpty()) {
//                    pyeong = ""
//                    squaremeter = ""
//                    return@OutlinedTextField
//                }
//                val numericValue = it.toFloatOrNull() ?: return@OutlinedTextField // 강제 종료
//                pyeong = it
//                squaremeter = (numericValue * 3.306).toString()
//            }, label = {
//                Text("평")
//            }
//        )
//        OutlinedTextField(
//            value = squaremeter,
//            onValueChange = {},
//            label = {
//                Text("제곱미터")
//            }
//        )
//    } // 현재 이 상태가 전달되는 방식은 좋지 못한 방식이다.
    // 그래서 상태가 전달되는 범위를 좁히기 위해서 상태를 윗단으로 끌어올리는 것을 StateHoisting이라고 한다.

    // 단계 2: `Composable` 함수를 만들고 `Column`의 항목들을 옮기세요.
    // 단 상태는 옮기지 말아야 합니다.

    // 파라미터는 아래와 같이 구성합니다.
    // `pyeong: String, squareMeter: String, onPyeongChange: (String) -> Unit`
    PyeongToSquareMeterStateless(pyeong, squaremeter){
        if (it.isEmpty()) {
            pyeong = ""
            squaremeter = ""
            return@PyeongToSquareMeterStateless
        }
        val numericValue = it.toFloatOrNull() ?: return@PyeongToSquareMeterStateless // 강제 종료
        pyeong = it
        squaremeter = (numericValue * 3.306).toString()
    }
} // 하나의 컴포저블에만 상태를 넣을 수 있따.

@Composable // 다른 컴포저블은 샅애를 가지지 않게 할 수 있다.
fun PyeongToSquareMeterStateless(
    pyeong: String,
    squareMeter: String,
    onPyeongChange: (String) -> Unit // 이 것을 통해 상태를 바꿈
) { // state를 바꿀 책임을 위에 올리고 여기는 상태를 가지고 있지 않기 때문에 상태를 바꾸지 않을 것이다.
    Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = pyeong,
            onValueChange = onPyeongChange,
            label = {
                Text("평")
            }
        )
        OutlinedTextField(
            value = squareMeter,
            onValueChange = {},
            label = {
                Text("제곱미터")
            }
        )
    }
} // 이렇게 하면 테스트하기 쉬워 진다.

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    StateTheme {
        PyeongToSquareMeter()
    }
}
profile
모두 이루어져라

0개의 댓글