Hel*_*oCW 6 android android-jetpack-compose
我已经阅读了有关可组合函数的官方文档
但我无法理解可组合函数。
例如,rememberWatchState()是Composable代码 A 中的一个函数,但它不像普通函数那样定义我的应用程序的 UI。
Android中的Composable函数和普通函数有什么区别?
代码A
@Composable
fun ScreenHome_Watch(
watchState:WatchState = rememberWatchState()
){
val density= watchState.density
}
@Composable
fun rememberWatchState(): WatchState {
val context: Context = LocalContext.current
val temp = loadDBWarningValueWithPreference(context)
val watchState = WatchState(temp.toFloat(),LocalDensity.current)
return remember {
watchState
}
}
class WatchState(
private val alarmValue:Float,
val density: Density
){
...
}
fun drawDial(
drawScope: DrawScope,
watchState:WatchState
) {
...
}
Run Code Online (Sandbox Code Playgroud)
Thr*_*ian 11
@Composable注释就像一个范围,可以访问 Compose 函数(例如LaunchedEffect、SideEffect)remember或对象(例如currentComposer和 ),类似于挂起函数。
以下部分引用自Leland Richardson 的Under the hood of Jetpack Compose \xe2\x80\x94 Part 2 of 2文章。
\n// function declaration\nsuspend fun MyFun() { \xe2\x80\xa6 }\n \n// lambda declaration\nval myLambda = suspend { \xe2\x80\xa6 }\n\n// function type\nfun MyFun(myParam: suspend () -> Unit) { \xe2\x80\xa6 }\nRun Code Online (Sandbox Code Playgroud)\nKotlin\xe2\x80\x99s suspend 关键字作用于函数类型:您可以有一个\xe2\x80\x99s 挂起的函数声明、lambda 或类型。Compose 以同样的方式工作:它可以改变函数类型。
\n// function declaration\n@Composable fun MyFun() { \xe2\x80\xa6 }\n \n// lambda declaration\nval myLambda = @Composable { \xe2\x80\xa6 }\n \n// function type\nfun MyFun(myParam: @Composable () -> Unit) { \xe2\x80\xa6 }\nRun Code Online (Sandbox Code Playgroud)\n这里重要的一点是,当您使用@Composable注释函数类型时,您\xe2\x80\x99正在更改其类型:没有注释的相同函数类型与注释类型不兼容。此外,挂起函数需要调用上下文,这意味着您只能在另一个挂起函数内部调用挂起函数。
\nfun Example(a: () -> Unit, b: suspend () -> Unit) {\n a() // allowed\n b() // NOT allowed\n}\n \nsuspend \nfun Example(a: () -> Unit, b: suspend () -> Unit) {\n a() // allowed\n b() // allowed\n}\nRun Code Online (Sandbox Code Playgroud)\n可组合的工作方式相同。这是因为有\xe2\x80\x99s 一个调用上下文对象,我们需要通过所有调用来线程化。
\nfun Example(a: () -> Unit, b: @Composable () -> Unit) {\n a() // allowed\n b() // NOT allowed\n}\n \n@Composable \nfun Example(a: () -> Unit, b: @Composable () -> Unit) {\n a() // allowed\n b() // allowed\n}\nRun Code Online (Sandbox Code Playgroud)\n我们\xe2\x80\x99传递的调用上下文是什么?为什么我们需要这样做?
\n我们称这个对象为Composer. Composer 的实现包含与 Gap Buffer 密切相关的数据结构。这种数据结构通常用于文本编辑器。
让\xe2\x80\x99s 看一下计数器的示例。
\n@Composable\nfun 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这是我们要编写的代码,但让\xe2\x80\x99s 看看编译器会做什么。
\n当编译器看到 Composable 注释时,它会插入附加参数并调用函数体。
\n首先,编译器添加对composer.start方法的调用,并向其传递编译时生成的关键整数。
\nfun Counter($composer: Composer) {\n $composer.start(123)\n var count by remember { mutableStateOf(0) }\n Button(\n text="Count: $count",\n onPress={ count += 1 }\n )\n $composer.end()\n}\nRun Code Online (Sandbox Code Playgroud)\n例如,LazyRow 或 LazyColumns 的 LazyListScope 接收器内容未使用 @Composable 注释,这不允许您调用其他可组合项
\n@Composable\nfun LazyColumn(\n // Rest of params\n // Non Composable scope\n content: LazyListScope.() -> Unit\n) {\n // Implementation details\n}\n\nLazyColumn(){ // LazyListScope\n // You can\'t add Composable here because this scope is LazyListScope\n // which is not annotated with @Composable, and returns compiler error\n // Row(){}\n \n items(100){\n Row() {\n \n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n您不能从中调用 Composable 函数,LazyListScope但可以在内部调用,items因为它的内容是 @Composable 函数。
fun item(\n key: Any? = null,\n contentType: Any? = null,\n content: @Composable LazyItemScope.() -> Unit\n) {\n error("The method is not implemented")\n}\nRun Code Online (Sandbox Code Playgroud)\n您需要一个带有 @Composable 注释的作用域来调用其他 @Composable 函数。
\n可组合函数并不强制必须是 UI 函数。某些函数(例如SideEffect或 )LaunchedEffect用于在您的 Composable 函数成功进入组合时运行。
@Composable\n@NonRestartableComposable\n@OptIn(InternalComposeApi::class)\nfun SideEffect(\n effect: () -> Unit\n) {\n currentComposer.recordSideEffect(effect)\n}\nRun Code Online (Sandbox Code Playgroud)\n或者不仅检查它何时进入合成,还检查它何时退出DisposableEffect
@Composable\nprivate fun NonUIComposableSample() {\n\n val context = LocalContext.current\n\n var counter by remember { mutableStateOf(0) }\n var color by remember { mutableStateOf(Color.Red) }\n\n if (counter in 3..5) {\n DisposableEffect(Unit) {\n\n Toast.makeText(context, "Entering Composition counter: $counter", Toast.LENGTH_SHORT).show()\n color = Color.Yellow\n onDispose {\n color = Color.Green\n Toast.makeText(context, "Exiting Composition counter: $counter", Toast.LENGTH_SHORT).show()\n }\n }\n }\n\n Button(onClick = { counter++ }) {\n Text("Counter: $counter", color = color)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n在此示例中,具有 DisposableEffect 的块在计数器为 3 时进入合成,并在不再满足条件时退出。
\n另外,productState是另一个 @Composable 非 ui 函数,它启动一个作用范围为 Composition 的协程,可以将值推送到返回的 State 中。使用它将非 Compose 状态转换为 Compose 状态,例如将 Flow、LiveData 或 RxJava 等外部订阅驱动状态引入 Composition。
\nCompose 是一种数据结构,保存了组合中的所有对象,整个树按执行顺序排列,实际上是对树的深度优先遍历。
\n| 归档时间: |
|
| 查看次数: |
2285 次 |
| 最近记录: |