在这篇短文中,我将清楚地解释derivedStateOf{}
和使用带有keys的remember{}
之间的区别。阅读完本文后,你将对它们之间的区别有非常清晰的认识。
先决条件
为了理解本文,你必须熟悉以下概念:
- • 在Compose中创建和记住状态
- • 状态与重新组合的关系
- • 重新组合
带有keys的remember{}
remember{}
函数用于在组合中记住状态。这有助于可组合函数在重新组合时记住先前的值。remember
函数还可以带有一些参数,称为“keys”。键可以是任何随时间而变化的值。该函数可以将多个键作为参数。在Compose中,我们使用状态来表示可以随时间改变的值。当传递给remember块的任何一个键的值发生更改时,remember
块的尾随lambda将被重新执行。如果需要记住状态并仅在另一个状态更改时重新计算,则这非常方便。 例如,假设您想在用户更改筛选器时过滤列表。您可以创建一个使用当前选定的筛选器作为键的remember块。仅当当前选定的筛选器更改时,过滤列表才会重新计算。
val filteredTasksByName by remember(currentlySelectedFilter) {
tasks.filter{ it.name == currentlySelectedFilter.filterName }
}
derivedStateOf
尽管乍一看,derivedStateOf
可能看起来像是 remember
的升级版,但它主要用于执行另一个重要功能。虽然 derivedStateOf
的尾随 lambda 表达式在引用的任何状态值发生更改时都会重新计算,但这消除了显式指定键的需要。
@Composable
fun someComposableFunction(){
.
.
.
var stateVariable by remember {
derivedStateOf {
// any state that is read within this block will cause
// this block to be re-executed when that state changes value.
}
}
.
.
.
}
如前所述,它用于执行另一个重要功能——减少不必要的重新组合。在记住的情况下,即使已更改的键设置为先前设置的相同值,lambda也会重新计算。我将使用我在另一篇文章中使用的示例,其中详细介绍了derivedStateOf
。如果您想了解有关derivedStateOf
是什么以及应在何时使用它的详细指南,请查看该文章。假设我们想在用户滚动过惰性列表中的第3个项目时显示“滚动到顶部”FAB(浮动操作按钮)。如果我们使用remember {}
,可能会像这样做。
@Composable
fun someComposableFunction(){
.
.
var isScrollUpFabVisible = remember(lazyListState.firstVisibleItemIndex){
lazyListState.firstVisibleItemIndex > 3
}
.
.
if(IsScrollUpFabVisible){
/* Display the floating action button*/
}
.
.
}
这个实现虽然可以工作,但是会导致很多不必要的重新组合。lazyListState.firstVisibleItemIndex
属性会非常频繁地变化。这很有道理,因为当用户滚动列表时,第一个可见项的索引会随之变化。这会导致可组合的函数在用户持续滚动时重新组合!如果我们把状态变化看作一系列数据流,那么就会得到类似于这样的数据流——false、false、false、false、true、true、true……等等。将状态从 true 到 false 和相反的方向上移动时重新组合会更好,这正是 derivedStateOf
所做的。它查看新值并将其与旧值进行比较。如果两者相同,则不会更改状态的值。由于状态的值没有改变,读取该状态的可组合函数也不会重新组合。因此,减少了不必要的重新组合。这是 derivedStateOf
的主要功能,应该在使用状态的可组合函数需要比状态更改频率低时使用。可以使用下面的代码更有效地实现相同的功能:
@Composable
fun someComposableFunction(){
.
.
var isScrollUpFabVisible by remember {
derivedStateOf { lazyListState.firstVisibleItemIndex > 3}
}
.
.
if(IsScrollUpFabVisible){
/* Display the floating action button*/
}
.
.
}
结论
本文介绍了 derivedStateOf
和带有键值的 remember
之间的区别。虽然它们都可以实现相似的功能,但 derivedStateOf
主要用于减少不必要的重组,而 remember
则用于记忆状态。当状态更改的速率高于组合函数的重组速率时,应该使用 derivedStateOf
。记住,remember
是一个组合函数,而 derivedStateOf
是一个普通的 Kotlin 函数。希望你能够理解这两个函数之间的区别,并在编程中灵活使用它们。
欢迎关注我的公众号“虎哥Lovedroid”,原创技术文章第一时间推送。
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/28855.html