还记得我们之前在 项目初探 的时候,留下的思考题吗?
Greeting里面的getPlatform()方法是如何获取到各端的接口实现的?
这个里面其实就涉及到了我们跨平台的核心特性,今天我们就来聊聊这个特性,以及为什么Compose Multiplatform 可以跨平台。
想更多了解Compose Multiplatform,也可以看看其他文章
- Compose Multiplatform 之旅 — 启程
- Compose Multiplatform 之旅 — 项目初探
- Compose Multiplatform 之旅 —做一个自己的项目(别踩白块)
- Compose Multiplatform 之旅—看看大佬在做啥
- Compose Multiplatform 之旅—为什么可以跨平台
- Compose Multiplatform 之旅—声明式UI
- Compose Multiplatform 之旅—跳转、导航(Voyager)
- Compose Multiplatform 之旅 — 数据存储(multiplatform-settings、sqldelight)
- Compose Multiplatform 之旅 — 网络请求(Ktor)
- Compose Multiplatform 之旅 — 图标、图片展示(coil)
一. Kotlin Multiplatform 的支持
Kotlin Multiplatform 是 Compose Multiplatform 的基础,提供了跨平台共享代码的能力。有了跨平台的基础能力,才有了CMP在上层进一步开发的可能。KMP允许开发者在公共模块中编写共享逻辑,并在每个平台上针对平台特定的功能实现少量平台代码。
-
Common Module (共享模块)
包含通用逻辑和 UI 代码,使用 Compose 提供的统一 API 构建 UI。 -
Platform Module (平台特定模块)
实现与具体平台相关的功能,如 iOS 的 Swift 接口、Android 的特定 View,或者 Desktop 和 Web 的渲染细节。
而KMP是如何做到同样的代码,能够在多端运行的呢?
1.编译器的支持
Kotlin 编译器针对不同平台进行了定制。对于 JVM 平台,编译器可以将 Kotlin 代码编译成 Java 字节码。对于 JavaScript 平台,编译器可以把 Kotlin 代码编译成 JavaScript 代码。在 Kotlin - Native 环境下,编译器可以生成针对特定操作系统的机器码,直接在本地环境运行,而不需要虚拟机的支持。
2.常用的基础库支持
对于日常开发来说,一些基本的系统能力支持,我们才能够更好的开发。Kotlin Multiplatform提供了还是算完备的标准库支持。像异步操作可以用kotlinx.coroutines,JSON解析可以用kotlinx.serialization, 网络请求可以用Ktor等。
3.expect
和 actual
特性
这个特性,就可以回答我们上面说的思考题。
expect
:预期声明,可以是函数、属性、类、接口、枚举或注解,在commonMain中定义。这些预期声明不包含实现代码,可以作为平台无关的 API 供共通代码使用。
actual
:实际声明,在androidMain、iosMain、jsMain、jvmMain的具体逻辑实现,需要与expect 一一对应,否则编译会报错。
这个有点像设计模式里面的策略模式,在commonMain定义好expect的接口,在各个平台里面使用actual ,对接口进行实现。不过在调用时,不是动态是生成对应的对象,而是在编译时,根据你编译的目标平台,直接替换成对应平台的实现。
interface Platform {
val name: String
}
// commonMain中进行预期声明
expect fun getPlatform(): Platform
class AndroidPlatform : Platform {
override val name: String = "Android ${Build.VERSION.SDK_INT}"
}
// android 的实际声明
actual fun getPlatform(): Platform = AndroidPlatform()
class IOSPlatform: Platform {
override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}
// ios 的实际声明
actual fun getPlatform(): Platform = IOSPlatform()
class JVMPlatform: Platform {
override val name: String = "Java ${System.getProperty("java.version")}"
}
//桌面端jvm 的实际声明
actual fun getPlatform(): Platform = JVMPlatform()
二.Skia 支持跨平台
除了KMP 跨平台的支持外,渲染引擎的跨平台支持也尤为重要,只有渲染引擎能够在多个平台使用,我们的UI才能在各个平台进行渲染
而Skia正是一个开源的 2D 图形库,它提供跨多种硬件和软件平台的通用 API。Skia 被广泛应用于 Google Chrome、ChromeOS、Android、Flutter 中。 它支持多种操作系统和平台,包括 Windows、macOS、iOS、Android、Ubuntu、Debian 和 Fedora Linux 等。
同时针对Kotlin,基于Skia也封装了的一个Skiko库,Kotlin 进行调用也更为便捷。
此外还有现代声明式编程风格的统一,通过描述 UI 的状态来动态渲染用户界面,这种范式易于跨平台实现一致的用户体验。未来还可能实现,Compose 直接转成 Swift的能力,从编译器层面实现跨平台,而不是使用自绘引擎实现。
结语
Kotlin Multiplatform 这种基于编译器层面实现,一端开发,多端运行的想法令人赞叹!让我们一起继续深入探究Compose Multiplatform这个神奇的世界吧。