一点 Kotlin 的小感想
Delegated properties 加上 remember 函数, 可以把 Composable 中的状态变量变成类似 C 中的 static 局部变量, 比如这里:
@Composable fun EditNumberField() { var amountInput by remember { mutableStateOf("") } TextField( value = amountInput, onValueChange = { amountInput = it }, ) }
每次 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
. 最后的两个函数如下:
@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, ) }