Compose Multiplatform 之旅 — 项目初探

1,576 阅读3分钟

上次我们提到了如何创建并运行一个 Compose Multiplatform的项目。

今天,我们来说一说Compose Multiplatform 项目一般的结构,以及如何跨平台调用的。

想更多了解Compose Multiplatform,也可以看看其他文章

底层实现

对于安卓来说,Compose之前就是Android 的一个声明式 UI 框架,底层是直接基于安卓底层的Skia 进行渲染。

对于其它端,Compose为了支持桌面端、IOS、Web的跨平台,封装了一个 Skiko,底层仍然是Skia。Skiko是特别为 Kotlin/Multiplatform 项目设计,提供了更便捷的 Kotlin 接口。

Pasted image 20241126203958.png

项目结构

下面是创建Hello World工程自动创建好的项目结构。主要分为shared 和 composeApp两大块。

  • shared: 主要做一些通用的业务逻辑,若不同端存在差异,可以定义接口,让各平台去进行实现。
  • composeApp: 是各平台APP 实现层,因为是Hello World项目,是把各端都放到一个模块,减少一些不必要的模块依赖,更为清晰。实际项目中,可能多端代码仓库不在同一个地方,更可能的是拆分为多个模块。
  • iosApp:因为iOS 是需要用xcode单独编译的,是需要一个单独的工程,进行一些项目的配置。所以这里也是单独到一个模块了。
    project-root/
    │
    ├── shared/          # 共享代码模块
    │ ├── commonMain/    # 平台无关的逻辑,定义接口,各业务端实现
    │ ├── androidMain/   # Android相关业务逻辑实现
    │ ├── iosMain/       # iOS相关业务逻辑实现
    │ ├── jvmMain/       # 桌面相关业务逻辑实现
    │ └── wasmJsMain/    # Web相关业务逻辑实现
    │
    ├── composeApp/      # APP 实现模块
    │ ├── commonMain/    # 通用UI,调用shared/commonMain逻辑,实现UI展示 
    │ ├── androidMain/   # Android APP实现
    │ ├── iosMain/       # iOS APP实现,提供ComposeUIViewController给iOS工程
    │ ├── jvmMain/       # 桌面 APP实现
    │ └── wasmJsMain/    # Web 网页实现
    │
    ├── iosApp/          # iOS 平台工程,在xcode上也是运行该工程
    │ └── src/
    │
    ├── gradle/          # 项目gradle wrapper 以及 相关版本配置
    └── build.gradle.kts # 项目构建文件

调用过程

看各个平台的入口代码

  • Android: MainActivity
  • IOS:MainViewController
  • 桌面:jvmMain/main
  • Web: wasmJsMain/main

实现上都很简单,只是创建了一个 App() 对象。 App就是一个我们的Compose 实现的UI,通过调用同一个Compose UI ,就可以在不同端,实现同样的UI效果了。

Pasted image 20241127211155.png

在App 的UI中,可以看到调用了一个Greeting().greet(),这个就是调用的shared中的通用业务代码。实现同样的业务逻辑。

在Greeting中,有一个 通用的业务逻辑,"Hello, ${platform.name}!" ,但是各端的name是不一样的。针对这种存在差异的地方,需要各端有自己的实现。通过定义了一个Platform接口,各个端实现自己的逻辑,再通过getPlatform()方法,获取到各端的实现,调用到各端的逻辑。

Pasted image 20241127212409.png

结语

至此,Compose Multiplatform 项目结构,以及如何跨平台调用的就介绍完了,我们也留一个思考题:Greeting里面的getPlatform()方法是如何获取到各端的接口实现的呐?