天天看点

Compose 中的附带效应

关键词

  1. 附带效应是指在可组合函数范围之外发生的应用状态变化
  2. 效应是一种可组合函数,该函数不会发出界面,并且在组合完成后产生附带效应。
效应名称 作用 用例
LaunchedEffect 在某个可组合项的作用域内运行挂起函数 snackBar显示
rememberCoroutineScope 获取组合感知作用域,以便在可组合项外启动协程 snackBar显示
rememberUpdatedState 在效应中引用某个值,该效应在值改变时不应重启 如果在 LaunchedEffect 运行时 onRefreshPosts 或 onErrorDismiss 发生变化, 请不要重新启动效果并使用最新的 lambda 值
DisposableEffect 需要清理的效应 -
SideEffect 将 Compose 状态发布为非 Compose 代码 FirebaseAnalytics 改变用户类型,转换为普通对象
produceState 将非 Compose 状态转换为 Compose 状态 -
derivedStateOf 将一个或多个状态对象转换为其他状态 -
snapshotFlow 将 Compose 的 State 转换为 Flow -

解释:不会发出界面指的是不会生成界面元素,可组合函数是被添加@Compose注解的函数

derivedStateOf:将一个或多个状态对象转换为其他状态,状态由其他状态转换而来。对于简单状态不需要转换的可以直接remember函数

如果某个状态是从其他状态对象计算或派生得出的,请使用 derivedStateOf。使用此函数可确保仅当计算中使用的状态之一发生变化时才会进行计算。

以下示例展示了基本的“待办事项”列表,其中具有用户定义的高优先级关键字的任务将首先显示:

@Composable
fun TodoList(highPriorityKeywords: List<String> = listOf("Review", "Unblock", "Compose")) {

    val todoTasks = remember { mutableStateListOf<String>() }

    // Calculate high priority tasks only when the todoTasks or highPriorityKeywords
    // change, not on every recomposition
    val highPriorityTasks by remember(highPriorityKeywords) {
        derivedStateOf { todoTasks.filter { it.containsWord(highPriorityKeywords) } }
    }

    Box(Modifier.fillMaxSize()) {
        LazyColumn {
            items(highPriorityTasks) { /* ... */ }
            items(todoTasks) { /* ... */ }
        }
        /* Rest of the UI where users can add elements to the list */
    }
}      

在以上代码中,derivedStateOf 保证每当 todoTasks 发生变化时,系统都会执行 highPriorityTasks 计算,并相应地更新界面。如果 highPriorityKeywords 发生变化,系统将执行 remember 代码块,并且会创建新的派生状态对象并记住该对象,以代替旧的对象。由于执行过滤以计算 highPriorityTasks 的成本很高,因此应仅在任何列表发生更改时才执行,而不是在每次重组时都执行。

此外,更新 derivedStateOf 生成的状态不会导致可组合项在声明它的位置重组,Compose 仅会对返回状态为已读的可组合项(在本例中,指 LazyColumn 中的可组合项)进行重组。