Thr*_*ian 7 android android-jetpack-compose
查看 codelab 的基本教程,有一个片段可以在单击时增加按钮上的计数器
@Composable
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
val counterState = remember { mutableStateOf(0) }
Column(modifier = Modifier.fillMaxHeight()) {
Column(modifier = Modifier.weight(1f)) {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
}
Counter(
count = counterState.value,
updateCount = { newCount ->
counterState.value = newCount
}
)
}
}
@Composable
fun Counter(count: Int, updateCount: (Int) -> Unit) {
Button(
onClick = { updateCount(count + 1) },
colors = ButtonConstants.defaultButtonColors(
backgroundColor = if (count > 5) Color.Green else Color.White
)
) {
Text("I've been clicked $count times")
}
}
Run Code Online (Sandbox Code Playgroud)
很明显,remember { mutableStateOf(0) }存储状态/值。我的问题是记忆在幕后做了什么。使用var count = remember { 0 }或mutableStateOf(0)不使用 记住不会增加值。
fun MyScreenContent(names: List<String> = listOf("Android", "there")) {
var count = remember { 0 }
Column(modifier = Modifier.fillMaxHeight()) {
Column(modifier = Modifier.weight(1f)) {
for (name in names) {
Greeting(name = name)
Divider(color = Color.Black)
}
}
Counter(
count = count,
updateCount = { newCount ->
count = newCount
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码段不会更新打印的值Text,记得只适用于MutableState?
Thr*_*ian 53
要了解合成和重组的工作原理,您可以查看Leland Richardson 撰写的Under the hood of Jetpack Compose 文章,该文章很好地描述了内部工作原理,还有 YouTube视频。这个答案大部分都使用文章作为参考,并引用了其中最多的内容。
\nComposer 的实现包含与Gap Buffer密切相关的数据结构。这种数据结构通常用于文本编辑器。
\n间隙缓冲区表示具有当前索引或游标的集合。它是通过平面数组在内存中实现的。该平面数组大于它所表示的数据集合,未使用的空间称为间隙。
\n基本上在可组合函数槽表附近添加空间,以便能够以高成本动态更新 UI,因为get、move、insert和delete\xe2\x80\x94 是恒定时间操作,除了移动间隙之外。移动间隙的时间复杂度为O(n),但这种情况并不经常发生,您需要更改所有 UI 结构,平均而言,UI 不会改变结构太多。
@Composable\n fun Counter() {\n var count by remember { mutableStateOf(0) }\n Button(\n text="Count: $count",\n onPress={ count += 1 }\n )\n }\nRun Code Online (Sandbox Code Playgroud)\n当编译器看到 Composable 注释时,它会插入附加参数并调用函数体。\n首先,编译器添加对该方法的调用composer.start,并向其传递一个编译时生成的关键整数。
fun Counter($composer: Composer) {\n $composer.start(123)\n var count by remember($composer) { mutableStateOf(0) }\n Button(\n $composer,\n text="Count: $count",\n onPress={ count += 1 },\n )\n $composer.end()\n}\nRun Code Online (Sandbox Code Playgroud)\n当这个作曲家执行时,它会执行以下操作:
\n数据结构现在保存了组合中的所有对象,整个树按执行顺序,有效地深度优先遍历树。
\n因此remember需要存储 amutableState()以从先前的组合中获取值,并且mutableState()需要触发一个。
并且MutableState接口使用@Stable注解
@Stable\ninterface MutableState<T> : State<T> {\n override var value: T\n operator fun component1(): T\n operator fun component2(): (T) -> Unit\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\nStable 用于向 compose 编译器传达有关特定类型或函数的行为方式的一些保证。
\n当应用于类或接口时,Stable 表明以下条件必须为真:
\n\n
\n- 对于相同的两个实例,equals 的结果将始终返回相同的结果。
\n- 当类型的公共属性发生变化时,组合将会得到通知。
\n- 所有公共属性类型都是稳定的。\n当应用于函数或属性时,[稳定]注释表示如果传入相同\n参数,该函数将返回相同的结果。仅当参数\n和结果为它们本身是稳定的、不可变的或原始的。
\n此注释暗示的不变量由 compose 编译器用于优化,并且如果不满足上述假设,则具有未定义的行为。因此,除非确定满足这些条件,否则不应使用此注释。
\n
另一个带有描述 Compose 如何工作的视频的来源。
\nThr*_*ian 14
Codelab 示例提到了Remember和mutableState作为
\n\n\n对状态变化做出反应是 Compose 的核心。Compose\napps 通过调用可组合函数将数据转换为 UI。如果您的数据发生变化,您可以使用新数据调用这些功能,从而创建更新的 UI。Compose 提供了用于观察应用程序数据变化的工具,它会自动调用您的函数\xe2\x80\x94,这\n称为重构。Compose 还会查看单个可组合项\n需要哪些数据,以便它只需要\n重新组合数据已更改的组件,\n并可以跳过组合那些不受影响的\n组件。
\n在底层,Compose 使用自定义 Kotlin 编译器插件,因此当底层数据发生变化时,可以重新调用可组合函数来更新 UI 层次结构。
\n要将内部状态添加到可组合项,请使用 mutableStateOf\n 函数,它提供可组合的可变内存。为了避免每次重组都有不同的状态,请使用 Remember 来记住可变状态。而且,如果屏幕上不同位置有多个可组合实例,则每个副本都将获得其自己的状态版本。您可以将内部状态视为类中的私有变量。
\n
remember{X}并且remember{mutableStateOf(X)}在不同的场景下都有用。
当您的对象不需要在每次重新组合时实例化时,需要第一个,并且还有另一个触发器可以触发组合。
\n一个例子是remember{Paint()},任何不需要多次实例化或实例化占用大量内存的对象。如果拥有此对象的可组合项被重组,则对象的属性不会更改remember,这要归功于 ,如果您不使用,则remember您的对象会在每次重组时实例化,并且先前设置的所有属性都会重置。
如果您需要trigger(mutableStateOf) 并且需要具有最新值(记住),就像有问题一样,请选择remember{mutableStateOf()}
Dab*_*ber 12
记住 - 允许您记住先前重构调用的状态,仅此而已。因此,例如,如果您在初始运行时随机化颜色。随机颜色将被计算一次,并在需要重新组合时重复使用。
所以......记住=存储值以防recompose被调用。
现在第二件事是知道何时应该真正触发重新编写。并且有可变状态来提供帮助。
mutablestate = 存储值 AND 以防我使用此数据更新所有元素的值触发器重构。
| 归档时间: |
|
| 查看次数: |
1704 次 |
| 最近记录: |