赞
踩
本文是 Compose 系列的第二篇文章。在第一篇文章中,我已经阐述了 Compose 的优点、Compose 所解决的问题、一些设计决策背后的原因,以及这些内容是如何帮助开发者的。此外,我还讨论了 Compose 的思维模型、您应如何考虑使用 Compose 编写代码,以及如何创建您自己的 API。
在本文中,我将着眼于 Compose 背后的工作原理。但在开始之前,我想要强调的是,使用 Compose 并不一定需要您理解它是如何实现的。接下来的内容纯粹是为了满足您的求知欲而撰写的。
@Composable 注解意味着什么?
如果您已经了解过 Compose,您大概已经在一些代码示例中看到过 @Composable 注解。这里有件很重要的事情需要注意—— Compose 并不是一个注解处理器。Compose 在 Kotlin 编译器的类型检测与代码生成阶段依赖 Kotlin 编译器插件工作,所以无需注解处理器即可使用 Compose。
这一注解更接近于一个语言关键字。作为类比,可以参考 Kotlin 的 suspend 关键字:
- // 函数声明
- suspend fun MyFun() { … }
-
- // lambda 声明
- val myLambda = suspend { … }
-
- // 函数类型
- fun MyFun(myParam: suspend () -> Unit) { … }
Kotlin 的 suspend 关键字适用于处理函数类型: 您可以将函数、lambda 或者函数类型声明为 suspend。Compose 与其工作方式相同: 它可以改变函数类型。
- // 函数声明
- @Composable fun MyFun() { … }
-
- // lambda 声明
- val myLambda = @Composable { … }
-
- // 函数类型
- fun MyFun(myParam: @Composable () -> Unit) { … }
这里的重点是,当您使用 @Composable 注解一个函数类型时,会导致它类型的改变: 未被注解的相同函数类型与注解后的类型互不兼容。同样的,挂起 (suspend) 函数需要调用上下文作为参数,这意味着您只能在其他挂起函数中调用挂起函数:
- fun Example(a: () -> Unit, b: suspend () -> Unit) {
- a() // 允许
- b() // 不允许
- }
-
-
- suspend
- fun Example(a: () -> Unit, b: suspend () -> Unit) {
- a() // 允许
- b() // 允许
- }
Composable 的工作方式与其相同。这是因为我们需要一个贯穿所有的上下文调用对象。
- fun Example(a: () -> Unit, b: @Composable () -> Unit) {
- a() // 允许
- b() // 不允许
- }
-
-
- @Composable
- fun Example(a: () -> Unit, b: @Composable () -> Unit) {
- a() // 允许
- b() // 允许
- }
执行模式
所以,我们正在传递的调用上下文究竟是什么?还有,我们为什么需要传递它?
我们将其称之为 "Composer"。Composer 的实现包含了一个与 Gap Buffer (间隙缓冲区) 密切相关的数据结构,这一
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。