最近 JetBarin 公司发布了 Compose Desktop[1]。是的,你没听错,就是 Google 用于 Android 上的 Compose[2]。
Jetpack Compose 是用于构建原生 Android 界面的新工具包。Jetpack Compose 使用更少的代码、强大的工具和直观的 Kotlin API 简化并加快了 Android 上的界面开发。
而现在,就可以编写同样的 UI 层代码,然后运行到 Android 和 Desktop 了。不难发现,这是 kotlin 一直在搞的套路,多平台共享代码。
使用了 Skia 进行硬件加速( 就是 Flutter 使用的 Skia ),可以与 AWT 和 Swing 进行互操作。
让我们先来一个 Hello World 试试水。
你可以更新到最新的 idea 2020.3,或者从 Github[3] 上拉取它的模板。这里我选择使用 idea。
在 kotlin 选项中找到 JetBrains Compose ,选择 Desktop uses Kotlin。
创建完成后等待 gradle 依赖下载。
但是在这里会出现问题,运行时报下面的错。
org/jetbrains/kotlin/cli/common/PropertiesKt org.jetbrains.kotlin.cli.common.PropertiesKt Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
经过排查,这是由 Gradle 和 java 14 引起的,Gradle 6.6 的版本会引起该问题,可以将 gradle 更改到 6.7 或者 6.5 重新进行构建。我这里修改到 6.5.1
目前 compose 的版本为 113 , 而通过 idea 创建的 版本为 63,所以更新版本。
以下为官方的 gradle.kts 配置
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.4.0"
// __UPDATE_COMPOSE_VERSION_MARKER__
id("org.jetbrains.compose") version (System.getenv("COMPOSE_TEMPLATE_COMPOSE_VERSION") ?: "0.1.0-build113")
}
group = "me.young"
version = "1.0-SNAPSHOT"
dependencies {
implementation(compose.desktop.currentOs)
}
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "KotlinJvmComposeDesktopApplication"
}
}
}
repositories {
jcenter()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
打开 main.kt, 运行 main 函数。
看样子还行,还是熟悉的界面 JavaFx , 还是熟悉的味道 Material Design 。让我们来瞅瞅代码。
fun main() = Window {
var text by remember { mutableStateOf("Hello, World!") }
MaterialTheme {
Button(onClick = {
text = "Hello, Desktop!"
}) {
Text(text)
}
}
}
通过通过点击按钮,来更改 text,从而来刷新界面。基本和其他声明式 UI ,大同小异,比如 flutter,swiftUI 等。
基本使用控件使用可以参考 androidx.compose[4] 文档。
针对桌面做了一些扩展,比如鼠标,键盘事件,系统的原生通知,系统的托盘菜单。
具体文档可以参考官方 JetBrains/compose-jb[5] 仓库
开发完成的应用可以直接打包为平台可执行文件。我使用的是 windows 平台。通过 packageMsi
命令打包为 exe 应用。
这里会下载 wix3[6] 。
这里可能会出现下载失败,如果下载失败,请手动到 Github 下载 wix311-binaries.zip。然后将文件命名为 wix311.zip 放在 build/wixToolset 下,重新运行 packageMsi 。
当你认为你要编译成功时, Gradle 再次报错。
������������, �����˴������MSI ��װ�����: � 汾 �ַ��������� MSI ���� [1.0-SNAPSHOT] ������: �������¹������ô��������� "win.msi.productVersion"��https://msdn.microsoft.com/en-us/library/aa370859%28v=VS.85%29.aspx��
夺命 � 错,打开连接一看,好像是指定版本有问题, 微软要求版本必须按照 major.minor.build 这样的方式进行指定,而且 major 的范围是 0-255,minor 的范围是 0-255,最后的 build 的范围是 0-65535 。
在 Gradle 中添加版本号。
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "Hello World"
version = "0.1.0"
}
更新 gradle 后重新 packageMsi。
仍旧是报错。这次是 IO 异常。
在 Gradle 中添加新的配置 vendor 。
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "Hello World"
version = "0.1.0"
vendor = "Example vendor"
}
经历了一番波折后终于可以打包成功。
打包后的 msi 在 build\compose\binaries\main\msi\Hello World-0.1.0.msi。
一个简单的 Hello World 大小在 40 mb 左右。
目前来说,项目还有很多 bug,毕竟才 Alpha,而且官方文档也有错误。例如打包这一块,很多问题需要自己摸索。
例如中文输入法的输入的情况下报错。
Exception in thread "AWT-EventQueue-0 @coroutine#2" java.lang.NullPointerException: event.text must not be null。
图标显示问题,在我这里显示一个黑框框。
但是,jvm 上的 GUI 技术有了新的发展未尝不是一件好事,可以一处编写,多端运行。
compose-jb[7]
JetBrains/compose-jb[8]
androidx.compose[9]
Jetpack Compose 基础知识[10]
[1]
Compose Desktop: https://www.jetbrains.com/lp/compose/
[2]
Compose: https://developer.android.com/jetpack/compose?hl=zh-cn
[3]
Github: https://github.com/JetBrains/compose-jb/tree/master/templates/desktop-template
[4]
androidx.compose: https://developer.android.com/reference/kotlin/androidx/compose/ui/package-summary?hl=zh-cn
[5]
JetBrains/compose-jb: https://github.com/JetBrains/compose-jb
[6]
wix3: https://github.com/wixtoolset/wix3
[7]
compose-jb: https://www.jetbrains.com/lp/compose/
[8]
JetBrains/compose-jb: https://github.com/JetBrains/compose-jb
[9]
androidx.compose: https://developer.android.com/reference/kotlin/androidx/compose/ui/package-summary?hl=zh-cn
[10]
Jetpack Compose 基础知识: https://developer.android.com/jetpack/compose/tutorial