Jetpack Compose 是用于构建原生 Android 界面的新工具包
您只需描述界面的外观,Compose 会负责完成其余工作
它与现有界面工具包兼容,因此您可以混合搭配使用经典视图和新视图,而且它从一开始就支持 Material 和动画。
Compose写法中,方法需要加上@Compose才行,所有可组合函数都必须带有此注释,此注释可告知 Compose 编译器:此函数旨在将数据转换为界面。
重组是指在输入更改时再次调用可组合函数的过程
通过跳过所有未更改参数的函数或 lambda,Compose 可以高效地重组。
组合函数中不应该去修改全局变量,如果其他组合函数依赖这个全局变量,那么就会有附带效应,组合函数的执行顺序就必须按到某个顺序来执行,这样不是Compose想要的。
如果您需要执行成本高昂的操作(例如从共享偏好设置读取数据),请在后台协程中执行,并将值结果作为参数传递给可组合函数。
当您在 Compose 中编程时,有许多事项需要注意:
- 可组合函数可以按任何顺序执行。
- 可组合函数可以并行执行。
- 重组会跳过尽可能多的可组合函数和 lambda。
- 重组是乐观的操作,可能会被取消。
- 可组合函数可能会像动画的每一帧一样非常频繁地运行。
Compose 可以通过并行运行可组合函数来优化重组
应为可以在多线程中运行,所以函数写入局部变量,则这并非线程安全或正确的代码。因为在多个地方同时调用改组合函数的时候,界面可能会出现错乱:
@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
var items = 0
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Column {
for (item in myList) {
Text("Item: $item")
items++ // Avoid! Side-effect of the column recomposing.
}
}
Text("Count: $items")
}
}
这个代码中items多线程的时候可能出现两个2等情况,界面就会出现问题。
如果界面的某些部分无效,Compose 会尽力只重组需要更新的部分。这意味着,它可以跳过某些内容以重新运行单个按钮的可组合项,而不执行界面树中在其上面或下面的任何可组合项。
/**
* Display a list of names the user can click with a header
*/
@Composable
fun NamePicker(
header: String,
names: List<String>,
onNameClicked: (String) -> Unit
) {
Column {
// this will recompose when [header] changes, but not when [names] changes
Text(header, style = MaterialTheme.typography.h5)
Divider()
// LazyColumn is the Compose version of a RecyclerView.
// The lambda passed to items() is similar to a RecyclerView.ViewHolder.
LazyColumn {
items(names) { name ->
// When an item's [name] updates, the adapter for that item
// will recompose. This will not recompose when [header] changes
NamePickerItem(name, onNameClicked)
}
}
}
}
/**
* Display a single name the user can click.
*/
@Composable
private fun NamePickerItem(name: String, onClicked: (String) -> Unit) {
Text(name, Modifier.clickable(onClick = { onClicked(name) }))
}
当 header 发生更改时,Compose 可能会跳至 Column lambda,而不执行它的任何父项。此外,执行 Column 时,如果 names 未更改,Compose 可能会选择跳过 LazyColumnItems
只要 Compose 认为某个可组合项的参数可能已更改,就会开始重组。重组是乐观的操作,也就是说,Compose 预计会在参数再次更改之前完成重组。如果某个参数在重组完成之前发生更改,Compose 可能会取消重组,并使用新参数重新开始。
如果您的可组合函数需要数据,它应为相应的数据定义参数。然后,您可以将成本高昂的工作移至组成操作线程之外的其他线程,并使用 mutableStateOf 或 LiveData 将相应的数据传递给 Compose。