#+title: 一点 Kotlin 的小感想 #+date: <2023-03-25 Sat 21:34> #+author: thebesttv [[https://kotlinlang.org/docs/delegated-properties.html][Delegated properties]] 加上 [[https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#remember(kotlin.Function0)][remember]] 函数, 可以把 Composable 中的状态变量 变成类似 C 中的 static 局部变量, 比如这里: #+begin_src kotlin @Composable fun EditNumberField() { var amountInput by remember { mutableStateOf("") } TextField( value = amountInput, onValueChange = { amountInput = it }, ) } #+end_src 每次 =TextField= 中的内容被修改, =amountInput= 就会被修改, 然后被记住. 这样一来, 在 recomposition 的时候 (即重新调用 =EditNumberField()= 时), =amountInput= 不会变成初始值 (空字符), 而是会记住上次的结果. 大量使用 lambda 函数, 并且用它来捕获变量. 如 State hoisting, 它将上面 =EditNumberField()= 中的状态变量 =amountInput= 提升到调用它的函数中 (=TipTimeScreen()=), 从而把 stateful Composable 变成 stateless 的, 也就 是, 主要会增加两个参数: - A =value: T= parameter, which is the current value to display. - An =onValueChange: (T) -> Unit= – callback lambda, which is triggered when the value changes so that the state can be updated elsewhere, such as when a user enters some text in the text box. 这个 =onValueChange= 是调用点传入的 lambda 函数, 它可以捕获位于调用点函 数中, 被提升了的 =amountInput=. 最后的两个函数如下: #+begin_src kotlin @Composable fun TipTimeScreen() { // State hoisting 允许本来 EditNumberField 私有的状态 amountInput // 被其他 Composable 共享, 从而计算 tip 的值 var amountInput by remember { mutableStateOf("") } val amount = amountInput.toDoubleOrNull() ?: 0.0 val tip = calculateTip(amount) Column() { EditNumberField( value = amountInput, onValueChange = { amountInput = it } // lambda 函数捕获 amountInput ) // 展示计算出的小费 Text(text = stringResource(R.string.tip_amount, tip)) } } @Composable fun EditNumberField( // 用于获取输入金额 value: String, onValueChange: (String) -> Unit ) { TextField( value = value, onValueChange = onValueChange, ) } #+end_src