查看原文
其他

10个问题带你看懂 Compose 跨平台

fundroid AndroidPub 2022-07-13
近日 JetBrains 正式发布了 Compose Multiplatform 1.0 版,这标志其在生产环境中使用的时机已经成熟。相信有不少人对它还不太熟悉,本文通过下面 10 个热门问题带大家认识这一最新的跨平台技术。

FAQ

  1. 与 Jetpack Compose 的关系?
  2. 是否会取代 Flutter ?
  3. 有何技术优势?1.0是否已稳定?
  4. Android Studio 还能使用吗?
  5. 性能怎么样?
  6. 生态建设如何?
  7. 桌面应用开发是否要引入 JVM ?
  8. Web 端开发是否已经成熟?
  9. 未来是否支持 iOS ?
  10. Jetpack 是否会跨平台?

正文开始前先统一一下文中的用语:

  • compose-jb:即 Compose Multiplatform,包含下面三者
  • compose-android:即 Jetpack Compose
  • compose-desktop:即 Compose for Desktop
  • compose-web:即 Compose for Web

1. 与 Jetpack Compose 的关系?

Jetpack Compose 是 Google 针对 Android 推出的新一代声明式 UI 工具包,完全基于 Kotlin 打造,天然具备了跨平台的使用基础。JetBrains 以 Jetpack Compose(后文简称 compose-android)为基础,相继发布了 compose-desktop 和 compose-web ,使 Compose 可以运行在更多不同平台。

Compose Multiplatform (后文简称 compose-jb)本质上是将 compose-desktop,compose-web 以及 compose-android 三者进行了整合,开发者可以在单个工程中使用同一套 Artifacts 开发出运行在 Android,Desktop(Windows, macOS, LInux)以及 Web 等多端的应用程序,工程中可以实现大部分代码的共享以此达到跨平台开发的目的。

所以在概念上 compose-jb 可以看做是 compose-android 的超集;在具体实现上 compose-jb 则是在 fork 了 compose-android 的源码基础上增加了对 Desktop 和 Web 侧的 API。compose-jb 与 compose-android 同步更新,compose-jb 的 1.0 版本目前对应到 compose-android 1.1.0-beta02,因此在通用的 API 上 compose-jb 与 compose-android 时刻保持一致,不同的只是包名发生了变化,所以你可以将你的 compose-android 代码低成本地迁移到 compose-jb 工程中。

Jetpack Compose( compose-android )Compose Multiplatform(compose-jb)
androidx.compose.runtime:runtimeorg.jetbrains.compose.runtime:runtime
androidx.compose.ui:uiorg.jetbrains.compose.ui:ui
androidx.compose.material:materialorg.jetbrains.compose.material:material
androidx.compose.fundation:fundationorg.jetbrains.compose.fundation:fundation

2. 是否会取代 Flutter ?

compose-jb 虽由 JetBrains 发布,但是作为 Flutter 的开发者 Google 对其也是乐见其成,因为 Compose 与 Flutter 虽然都是跨平台技术,但是两者定位不同所以不存在直接竞争关系。

Flutter 的定位就是移动端跨平台解决方案,它的一切能力建设都是围绕如何更好地“一次编写、随处运行”,首要目标就是为了降低移动应用的开发成本(虽然最近也扩展到 Desktop 以及 Desktop)。

compose-jb 的首要定位是一个声明式 UI 工具包,它的目标是通过更先进的开发范式提升 UI 开发效率。由于声明式开发思想适应性广泛,所以借助 Kotlin 成为一个跨平台框架便是水到渠成的事情。如果说是 Flutter 成就了 Dart,那么 Kotlin 则成就了 Compose ,借助 Kotlin 近年来持续高涨的的人气,Compose 的未来也充满想象空间。

compose-jb 的受众主要有两类,首先是熟悉 Kotlin 与 Compose 的 Android 开发者,他们可以把自己的产品交付至更多平台;其次是 Kotlin 经验者,他们可以使用熟悉的语言更高效地开发包含 UI 的应用程序,像 JetBrains 这样的 IDE 公司就属于后者,他们迫切希望使用 Compose 替换 Swing 和 AWT 等基于 Java 的陈旧的技术栈,这也正是 compose-desktop 诞生的初衷。

3. 有何技术优势?1.0是否已稳定?

应用开发无非关注三件事:数据获取,状态管理,界面渲染。JetBrains 推出 Kotlin Multiplatform Mobile (简称 KMM) 实现了数据获取部分的跨平台,而 compose-jb 将跨平台的范围进一步覆盖到状态管理甚至界面渲染(基于 Skia)。

在一个 compose-jb 工程中,逻辑层(状态管理)以及数据层的代码在几乎可以完全共享。在表现层,常用的组件和布局例如 TextButtonColumn/Row 等都可以跨越 compose-android 与 compsose-desktop 通用,此外 compose-desktop  针对桌面系统的特性还提供了专用能力,比如可以感知鼠标行为和窗口大小、创建 ScrollbarsTooltipsTray

fun main() {
   Window {
       var windowSize by remember { mutableStateOf(IntSize.Zero) }
       var windowLocation by remember { mutableStateOf(IntOffset.Zero) }
       AppWindowAmbient.current?.apply {
           events.onResize = { windowSize = it }
           events.onRelocate = { windowLocation = it }
       }
       Text(text = "Location: ${windowLocation}\nSize: ${windowSize}")
   }
}

compose-desktop 还提供了 SwingPanel 用来嵌入使用既有的 Swing 组件。compose-desktop 在能力上完全可以替代 AWT 和 Swing 等现有 UI 框架。

compose-web 为 Web 开发者提供了专门的 DOM API,针对常用的 HTML 标签实现了对应的 Composable 组件,例如 DivPA 等等 ,同时提供了 attrs 方法以 key-value 的形式设置标签属性,一些常用属性也有专属方法;另外,基于 CSS-in-JS 技术 compose-web 允许开发者基于 DSL 定义 Style 样式。

fun main() {
    renderComposable("root") {
        var platform by remember { mutableStateOf("a platform") }
        P {
            Text("Welcome to Compose for $platform! ")
            Button(attrs = { onClick { platform = "Web" } }) {
                Text("...for what?")
            }
        }
        A("https://www.jetbrains.com/lp/compose-web") {
            Text("Learn more!")
        }
    }
}

compose-web 拥有 HTML 或 JSX 那样的结构化的变现能力,同时有具备了响应式状态管理能力,在 compose-jb 中还可以与 Desktop 和 Android 侧共享逻辑层代码。

稳定性方面,compose-jb 的大部分代码来自 Jetpack Compose,在 Android 端已经有上千款 App 接入,这足以保证其在 Android 端上的稳定性。

JetBrains 在几个月之前就将 Toolbox 应用从 C++ 和 Electron 迁移到了 compose-jb,并一直平稳运行,服务着超过 100 万的月活用户,常规的 UI 开发得到了检验。但是一些复杂功能可能还不够稳定,目前还有不少 issue 有待解决。

4. Android Studio 还能使用吗?

compose-jb 1.0 可以运行在 IntelliJ IDEA 2021.1 之后的版本中,IDEA 专门为其提供了工程向导和项目模板,指导开发者快速新建一个 compose-jb 项目。

开发者还可以通过插件市场下载 compose-desktop 侧的专用预览插件,在 Desktop 端实时预览添加 @Preview 的 Composalbe,提高开发效率。

Andorid Studio 作为 IntelliJ 平台下的 IDE ,自然也可以用于 compose-jb 项目的开发( IDEA 2021.1 对应 Android Studio Bumblebee 之后的版本)。AS 自带 Andoid 侧的预览能力,可以实时预览 UI 代码效果。此外 AS 对 Compose 的代码提示也更友好,比如非法调用 @Composable 函数时, IDE 会标红提示错误,而 IDEA 则只能在编译时发现错误。

5. 性能怎么样?

compose-android 和 compose-desktop 都使用 Skia 这一开源图形库进行渲染。Skia 在 Chrome,Flutter 等多个项目中广泛使用,性能方面得到了验证。Skia 还能支持平台特有的硬件加速技术,例如 DirectX,Metal 和 OpenGL 等,compose-jb 为没有硬件加速的设备也提供了优化的软件渲染方案。曾经有人将 compose-desktop 与 JavaFX 进行过实际对比测试,在通常情况下两者渲染性能相当,尽在极端情况下会略逊于 JavaFX,不过已经足够优秀了。

https://dev.to/gz_k/jetpack-compose-desktop-rendering-performances-4992

Web 侧 compose-jb 会通过 Kotlin/JS 编译器将代码仍然编译成 JS 代码在浏览器运行,所以理论上与传统的 Web 开发方式在性能上没有区别,由于 CSS-in-JS 实现都是在运行时生成 CSS,仅仅在这一点上相对于直接使用 CSS 前端项目可能略有一点性能损耗。

而在逻辑代码由于使用 Kotlin 作为开发语言,代码的执行效率要明显优于基于 Node 的 Electron 等同类跨平台框架,Kotlin/JVM 也保证了在桌面侧至少有与 Java 同样的运行时性能。

6. 生态建设如何?

compose-jb 依托 Kotin Multiplatform 的丰富类库,满足各种层面的能力开发,比如在架构、网络、数据存储等各方面都有不少优秀的的解决方案,一些代表性的项目如下:

CategoryLibraryDescription
ArchitectureDecomposeKotlin Multiplatform lifecycle-aware business logic components (aka BLoCs) with routing functionality and pluggable UI (Jetpack Compose, SwiftUI, JS React, etc.), inspired by Badoos RIBs fork of the Uber RIBs framework

MVIKotlinExtendable MVI framework for Kotlin Multiplatform with powerful debugging tools (logging and time travel), inspired by Badoo MVICore library

redux-kotlinRedux implementation for Kotlin (supports multiplatform JVM, native, JS, WASM)
NetworkKtorFramework for quickly creating connected applications in Kotlin with minimal effort

rsocket-kotlinRSocket Kotlin multi-platform implementation
StoragesqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL

Kodein-DBMultiplatform NoSQL database

multiplatform-settingsA Kotlin Multiplatform library for saving simple key-value data
Utils & OthersReaktiveKotlin multi-platform implementation of Reactive Extensions

koinA pragmatic lightweight dependency injection framework for Kotlin

kotlinx-datetimeKotlinX multiplatform date/time library

kotlin-loggingLightweight logging framework for Kotlin. A convenient and performant logging library wrapping slf4j with Kotlin extensions

More libraries:https://libs.kmp.icerock.dev/

7. 桌面应用开发是否要引入 JVM ?

compose-jb 在桌面端需要支持 Windows,macOS,Linux 等多套操作系统,基于 Kotlin/Native 的实现成本较高,因此现阶段 compose-desktop 仍然依赖 Kotlin/JVM 编译成 Java 字节码后再发布到各桌面系统。

compose-desktop 提供了专用的 Gradle 插件可以基于 jpackage 将 JVM 一同打包进各种格式的安装包,例如 Mac 的 dmg, Windows 的 msi,exe 以及 Linnux 的 deb 等,使用者无需额外安装 JDK ,可以像二进制程序一样开箱即用,此外还通过使用 jlink 技术只对 Java 模块的最小依赖进行打包以最大限度降低包体积。

$ ./gradlew package

> Task :packageDmg
WARNING: Using incubator modules: jdk.incubator.jpackage
The distribution is written to build/compose/binaries/main/dmg/DesktopApp-1.0.0.dmg

BUILD SUCCESSFUL in 11s
5 actionable tasks: 3 executed, 2 up-to-date

目前对 Kotlin/Native 编译器的适配工作也在进行中,未来 compose-desktop 有望通过切换到 Kotlin/Native 进一步提高应用的执行速度。

8. Web 端开发是否已经成熟?

compose-jb 中整合 compose-web 的最主要意义是帮助 Kotlin 开发者扩大应用的发布场景。如果你已经有一个 compose-desktop 或者 compose-android 项目,那么基于 compose-web 可以把产品快速发布到 Web 端,并共享其中大部分的逻辑代码。

compose-web 提供的声明式 DOM API 相对于 HTML+JS+CSS 这一传统技术栈在开发范式上更加先进。但如果你已经有 React 等前端框架的使用经验那么此项优势就不存在了。而且 compose-web 在建设速度上要落后于 compose-desktop,部分 HTML 标签以及属性还缺少对应的 DSL 实现,所以从单纯开发一个前端应用的角度看,如果你对 Kolin 没有执念的话,更推荐使用 React 等已有的成熟框架。

即使从跨平台的角度看, desktop-web 也仍然有改善空间。desktop-web 在 API 设计上尊重原有的 HTML 开发习惯,这也导致其 DSL 上与 compose-android 和 compose-desktop 的差异较大,不利于 UI 代码的共享。据悉 JetBrains 团队已经着手开发与其他两端风格一致的 DSL ,届时可以通过 HTML5 Canvas 实现 UI 统一绘制,提高跨平台的开发体验。

9. 未来是否支持 iOS?

compose-jb 目前没有对 iOS 端的支持,这是其成长为主流跨平台框架道路上的一个严重阻碍,因此可以大胆猜想 compose-jb 在未来一定会增加对 iOS 的支持,而且有迹象表明 JetBrains 已经偷偷开始了这方面工作。

有人就曾经在 compose-jb 工程中也发现过针对 iOS 的开发分支,而且 compose-ui 依赖的 Skiko 库也已经增加了对 iOS 的支持,理论上完全可以实现 iOS 侧渲染。由于 iOS 不使用 Kotlin/JVM ,所以在 Kotlin/Native 编译器以及 iOS 工具链等方面存在大量适配工作,毕竟 KMM 本身也还处于 alpha 阶段,iOS 端的开发体验还不理想,这可能就是 compose-ios 迟迟未发布的原因,但是未来是可以期待的。

那么在 compose-ios 还未出现的当下,如果你的应用有发布到 iOS 侧的需求,作为一个过渡方案可以先借助 KMM 推荐 D-KMP 架构实现逻辑层和数据层的代码共享,UI 侧现阶段可以使用 Swift-UI 等平台语言进行开发,等待 compose-ios 真正到来时再对 UI 代码进行迁移。

https://github.com/dbaroncelli/D-KMP-sample

10. Jetpack 是否会跨平台?

很多 Android 开发者习惯于 Compose 搭配 Android 的 Jetpack 系列组件一同使用,所以当一个 compose-android 项目被迁移到 compose-jb 时,不少人希望有对应的 KMP 版本 Jetpack 库可供使用。

在前不久 Android Dev Summit 上 Andorid Jetpack 团队就这个问题进行了回答,答案是暂时没有相关计划。

https://www.youtube.com/watch?v=QreLkok3Euk&t=565s

首先 Jetpack 中一些重度依赖 Andorid 平台特性的组件不适合发布 KMP 版本,而一些平台无关的组件例如 Hilt,Room 等,虽然具备 KMP 化的基础但仍然会谨慎启动,因为当前首要任务还是保证其在 Android 端的稳定使用。虽然当前没有计划但是 Jetpack 团队也表示了未来会尝试对部分 Jetpack 库进行 KMP 改造,他们很乐于帮助开发者能更低成本地完成项目向 KMP 的迁移。

对于开发者来说,如果你的项目近期有跨平台的需求,那么在技术选型上就要避免过度依赖 Jetpack ,而要像 KMP 的 Library 倾向。比如在逻辑层优先使用 Flow 而非 LiveData 等;在数据层也可以考虑使用 SQLDelight 替代 Room 。


- END -

推荐阅读


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存