Getting your feet wet
最初,Jetpack Compose是Android运行时的框架。Compose for Desktop是JVM的端口。
传统的GUI开发遵循OOP原则:单个图形组件封装状态并提供更改状态的行为。这就是AWT,Swing,JavaFX甚至SWT的工作方式。
Compose背后的想法是从OOP转向功能编程原则。组件由函数建模,状态作为其参数传递。状态更改时调用该函数。
这是一个Compose片段,在文本字段中显示一个值:
fun main() = Window { TextField("Hello world!") }
TextField 不是对构造函数的调用,而是对函数的调用 源代码确实确实消除了任何潜在的误解:
androidx.compose.material.TextField.kt @Composable fun TextField( value: String, ... )
State hoisting
从组件中删除状态称为状态提升。
大多数应用程序不会停止显示状态,而是提供了一种更新状态的方法。GUI应用程序中的经典示例是具有一个镜像文本字段值的标签。
这是在Compose中完成的方式:
fun main() = Window { val state = remember { mutableStateOf("Hello world!") } Row { TextField( state.value, { state.value = it } ) Text(state.value) } }
这值得一些解释:
就其本身而言,状态并不有趣,就像镜像文本字段的值一样。让我们想象一个简单的计算器用例,但将其限制为两个字段的整数值之和。
我们需要一个状态对象来保存总和。Compose提供了派生状态的概念:
fun main() = Window { val first = remember { mutableStateOf(0) } val second = remember { mutableStateOf(0) } val sum = derivedStateOf { first.value + second.value } Row { TextField(first.value.toString(), { first.value = it.toInt() }) TextField(second.value.toString(), { second.value = it.toInt() }) Text(sum.value.toString()) } }
您自己的撰写组件 创建自己的Compose组件就像实现一个函数并使用进行注释一样容易@Composable。
可将Composable应用于函数或lambda,以指示该函数/ lambda可用作构成从应用程序数据到树或层次结构的转换的组成部分。
—可组合的JavaDocs 上面的“计算器”代码段可以这样重写:
@Composable fun IntField(state: MutableState<Int>) = TextField( state.value.toString(), { state.value = it.toInt() } ) fun main() = Window { val first = remember { mutableStateOf(0) } val second = remember { mutableStateOf(0) } val sum = derivedStateOf { first.value + second.value } Row { IntField(first) IntField(second) Text(sum.value.toString()) } }
瞧,一个新的自定义组件!
用注释组件@Composable有一个重要的后果:它更改字节码中函数的签名。在此,它类似于协程。
这是该IntField函数的反编译版本:
public static final void IntField( androidx.compose.runtime.MutableState<java.lang.Integer>, androidx.compose.runtime.Composer<?>, int );
注意其他Composer参数。这就是Compose的魔力所在。
尽管编译器本身可以处理协程,但Compose需要专用的编译器插件来实现相同的结果。
撰写循环
到目前为止,我们将帖子集中在如何使用Compose进行开发上。我们避免了Compose的工作方式。尽管如此,我仍然相信使用Compose进行开发与使用其他框架有很大不同,因此值得一小节。
请记住,每个Compose组件都只是一个函数。这些函数是无状态的,并且通过传递参数从外部注入状态。状态更改时,Compose会检测到它并触发应用程序的重新绘制。再次调用函数,包括最上面的Window()一个。
Compose通过函数中添加的Composer参数来实现@Composable。最后,该Window功能设置了此机制。
有趣的是,Compose for Desktop依赖于从... Swing继承的GUI类JFrame。以下类图对此进行了总结:
记住状态
现在该写remember函数了。我们知道Compose会为每个状态更改调用函数。状态存储在这些函数内部的变量中。因此,当Compose调用一个函数时,状态会丢失并重置为其初始值。
运行不带该remember()功能的上述任何代码段:它们不会执行任何操作,因为每次更改后状态都会丢失。
为了跟踪重组的状态,您需要将其包装在一个remember块中。这告诉Compose缓存状态的值,并在调用函数后再次设置它-记住它。
第一个remember()功能将仅calculation在初始合成期间运行。进一步的重组将产生缓存的值。
重载函数允许传递一个或多个参数。如果自上次合成以来参数已更改,则Compose将调用该calculation函数并将状态设置为其返回值。否则,它的行为将与上面相同-缓存值。
其他注意事项
Α
首先,请注意Compose for Desktop是alpha。随时可能更改。您已被警告。
Gradle插件
由于其Android根源,Compose插件仅在Gradle中可用,该插件具有更改字节码中的功能签名的魔力。为此,请放心,我敢肯定没有Maven插件会正式发布。除非你写一个。
分配
该插件提供了package创建操作系统特定的安装程序的任务。这非常适合分发您的应用程序。
该任务jpackage在后台使用,因此请确保使用JDK 14或更高版本。另外,请注意,您仍然需要JRE才能执行已安装的应用程序。
标签
要标记字段,请避免Text像以前的框架一样在UI上放置组件。而是将它们自己设置在字段上。
TextField( value = "Hello world!", onValueChange = {}, label = { Text("Say hello!") }, )
没有任何值,Compose将文本标签显示为占位符。具有一个值或当它们获得焦点时,它将使它们移到上方。
显示标签
缺少功能
同样由于Android和框架的成熟,缺少一些重要的功能。我至少注意到以下几点:
结论
Jetpack Compose for Desktop似乎是一个有趣的举措。该框架尚处于初期阶段。但是,与所有其他Java桌面框架相比,功能方法是原始的。
可以在Github上以Maven格式找到此帖子的完整源代码。
原文链接:http://codingdict.com