[TIL] ๐ŸŒผ24/05/08๐ŸŒผ#State Delegates vs State Destructuring

0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
96/104
post-thumbnail
post-custom-banner

[TIL] ๐ŸŒผ24/05/08๐ŸŒผ#State Delegates vs State Destructuring

State Delegates vs State Destructuring

๐Ÿ“Œ๋„์›€๋ ๋งŒํ•œ ์ง€๋‚œ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ…

  • ํด๋”์˜ ์ด๋ฆ„๊ณผ ์ƒ‰์ƒ์„ ์ž…๋ ฅ๋ฐ›๋Š” ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ค‘, MutableState ์„ ์–ธ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋™์ž‘์— ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค!
  • ํด๋” ์ด๋ฆ„์„ ์ž…๋ ฅ๋ฐ›์€ ๊ฒฝ์šฐ(isNotBlank)์—๋งŒ ํด๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฒ„ํŠผ ์ƒํ…Œ๊ฐ€ enable ๋˜๋„๋ก ์ž…๋ ฅ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•จ
    -> ์ž…๋ ฅ๋ฐ›์€ ํด๋” ์ด๋ฆ„์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” MutableState ์ธ folderName ์„ ์–ธ
    -> folderName์˜ ๊ฐ’์ด ์ž…๋ ฅ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์ €์žฅํ•˜๋Š” nameValid๋ฅผ derivedStateOf side-effect๋ฅผ ์ด์šฉํ•ด ์„ ์–ธ
  • ์ด๋•Œ folderName์„ delegates๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•œ ๊ฒฝ์šฐ nameValid ๊ฐ’์ด ์ •์ƒ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์ง€๋งŒ,
    ๊ตฌ์กฐ ๋ถ„ํ•ด๋ฅผ ์‚ฌ์šฉํ•ด ์„ ์–ธํ•œ ๊ฒฝ์šฐ nameValid ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š”๋‹ค!
@Composable
fun AddFolderDialog(
    modifier: Modifier = Modifier,
    onDismissRequest: () -> Unit,
    addFolder: (String, String) -> Unit
) {
    // delegates
    var folderName by remember { mutableStateOf("") }
    val setFolderName = {it:String -> folderName = it}

    // destructing declarations
    //val (folderName, setFolderName) = remember { mutableStateOf("") }

    val (folderColorHex, setFolderColorHex) = remember { mutableStateOf(FolderColor.COLOR1.colorHex) }

    val nameValid by remember { derivedStateOf { folderName.isNotBlank() } }

    Dialog(
        onDismissRequest = onDismissRequest,
    ) {
        Card(
            modifier = modifier.height(IntrinsicSize.Min),
            shape = RoundedCornerShape(16.dp)
        ) {
            Column(
                modifier = modifier.padding(16.dp),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
            	// Dialog title
                Text(
                    modifier = modifier.fillMaxWidth(),
                    textAlign = TextAlign.Center,
                    text = stringResource(R.string.add_folder_title),
                )
                // ํด๋” ์ด๋ฆ„์„ ์ž…๋ ฅ๋ฐ›๋Š” Composable
                // ํด๋” ์ด๋ฆ„ ์ž…๋ ฅ ๊ฐ’ = folderName
                FolderNameInput(
                    modifier = modifier.padding(top = 16.dp),
                    value = folderName,
                    onValueChange = setFolderName
                )
                // ํด๋” ์ƒ‰์ƒ์„ ์ž…๋ ฅ๋ฐ›๋Š” Composable
                FolderColorSelect(
                    modifier = modifier.padding(top = 16.dp),
                    colorHexes = FolderColor.entries.map { it.colorHex }.drop(1),
                    selectedColorHex = folderColorHex,
                    onColorSelect = setFolderColorHex
                )
                // Dialog dismiss ๋ฒ„ํŠผ/confirm ๋ฒ„ํŠผ Composable
                // confirm ๋ฒ„ํŠผ enabel ์—ฌ๋ถ€ = nameValid
                DialogButtons(
                    modifier = modifier.padding(top = 16.dp),
                    dismissButtonLabelId = R.string.add_folder_negative,
                    onDismissRequest = onDismissRequest,
                    confirmButtonLabelId = R.string.add_folder_positive,
                    enableConfirmButton = nameValid,
                    onConfirmRequest = { addFolder(folderName, folderColorHex) }
                )
            }
        }
    }
}

๐Ÿ“Œ์ฐธ๊ณ ์ž๋ฃŒ

  • ์ด์™€ ๊ฐ™์ด ๋™์ž‘์— ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ ๋Š” MutableState๋ฅผ ์„ ์–ธํ•  ๋•Œ delegates๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๊ตฌ์กฐ ๋ถ„ํ•ด๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์— ์ฐจ์ด๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ!
  • Compose๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ state์— ๋Œ€ํ•œ ๋ชจ๋“  read/write์„ ์˜ต์ €๋น™ํ•œ๋‹ค!
    -> ์ด๋•Œ, Compose๋Š” snapshot system์„ ์‚ฌ์šฉํ•จ
  • MutableState์— write์„ ํ•˜๋Š” ๊ฒฝ์šฐ, state์˜ snapshot์— ์˜ํ–ฅ์„ ์คŒ
    -> write ์ „ snapshot๊ณผ ํ›„ snapshot์ด ๋‹ค๋ฅธ ๊ฒฝ์šฐ, snapshot conflict๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด recomposition ํŠธ๋ฆฌ๊ฑฐ
    -> ์ด๋•Œ ์ตœ๊ทผ์˜ snapshot์„ ๋ฐ”๋กœ state์˜ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜์ง€ X
    ๋‹ค์Œ recomposition cycle์—์„œ state์˜ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  candidate value๋กœ๋งŒ ์„ค์ •
    -> recomposition์ด ์‹ค์ œ๋กœ ์ˆ˜ํ–‰๋  ๋•Œ candidate value๋ฅผ state์˜ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ์„ค์ •
  • ์˜ˆ.
    (composition) state = 0, snapshot = 0
    -> state = 0, snapshot = 1 -> trigger recomposition, candidate value = 1
    -> state = 0, snapshot = 2 -> ใ€ƒ, candidate value = 2
    (recomposition) state = 2, snapshot = 2
  • delegates๋กœ MutableState์„ ์„ ์–ธํ•˜์—ฌ state์˜ ๊ฐ’์„ ์ฝ๋Š” ๊ฒฝ์šฐ
    -> MutableState.value operation์— delegate
    -> state์˜ ์‹ค์ œ ๊ฐ’์ด ์•„๋‹Œ candidate value ์ฝ์–ด์˜ด
  • ๊ตฌ์กฐ๋ถ„ํ•ด๋กœ MutableState์„ ์„ ์–ธํ•˜์—ฌ state์˜ ๊ฐ’์„ ์ฝ๋Š” ๊ฒฝ์šฐ
    -> MutableState.value operation ๋ถˆ๋ฆฌ์ง€ X, component1์„ ์„ค์ •ํ•  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ๋ถˆ๋ฆผ
    -> candidate value๊ฐ€ ์•„๋‹Œ, state์˜ ์‹ค์ œ ๊ฐ’ ์ฝ์–ด์˜ด
    -> recomposition์ด ์ผ์–ด๋‚˜์•ผ, re-initialize๋œ ์ตœ์‹ ์˜ state ๊ฐ’์„ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€