在 3月的时候通过我们大致知道了 Kuikly 的基本情况,Kuikly 是一个面向终端技术栈的跨端开发框架,完全基于kotlin语言开发,提供原生的性能和体验。

❝ 按照官方的说法:Kuikly是基于Kotlin Multiplatform 的 UI 与逻辑全面跨端综合解决方案,由腾讯大前端领域 Oteam(公司级)推出,目的在于提供一套一码多端、极致易用、动态灵活的全平台高性能开发框架。

当然,虽然是全平台,但是目前暂时只开源了 Android 和 iOS,鸿蒙部分 5 月才开源,而 Web 和 小程序暂定是 Q2:

那 Kuikly 如何实现跨平台?目前 Kuikly 主要是在 KMP 的基础上实现的自研 DSL 来构建 UI ,比如iOS 平台的 UI 能力就是 UIkit,而大家更熟悉的 Compose 支持,目前还处于开发过程中:

img

❝ SwiftUI 和 Compose 无法直接和 Kuikly 一起使用,但是 Kuikly 可以在 DSL 语法和 UI 组件属性对齐两者的写法,变成一个类 Compose 和 SwiftUI 的 UI 框架,也就是 Compose DSL 大概就是让 Kuikly 更像 Compose ,而不是直接适配 Compose?

那么大家可能会有疑问,既然借助了平台控件的能力,那它和 RN 有什么区别?

首先 Kuikly 是直接从编译产物的角度实现跨平台,它的编译产物与原生一致,和 RN 是在运行时转换为原生控件不同,Kotlin 是直接编译为对应平台的原生代码,所以在运行时其实就类似原生 code 。

那 Kuikly 又如何保证多端 UI 一致?答案是 Kuikly 实现了自己的一套「薄原生层」

首先在 Kotlin 层,Kuikly 将虚拟 Dom 方案优化为直调方案,这里 Kotlin View API 直调,避免 JSON 序列化/反序列化损耗,同时只维护一棵树,更轻量和O(1)同步UI更新:

之后,Kuikly 使用“非常薄”的原生层,该原生层只暴露最基本和无逻辑的 UI 组件(原子组件),也就是 Kuikly 在 UI 上只用了最基本的原生层 UI ,真正的 UI 逻辑主要在共享的 Kotlin 代码来实现:

❝ 通过将 UI 逻辑抽象到共享的 Kotlin 层,减少平台特定 UI 差异或行为差异的可能性,「薄原生层」充当一致的渲染目标,确保 Kotlin 定义的 UI 元素在所有平台上都以类似的方式显示。
打开网易新闻 查看精彩图片
img

也就是说,Kuikly 虽然会依赖原生平台的控件,但是大部分控件的实现都已经被「提升」到 Kuikly 自己的 Kotlin 共享层,目前 Kuikly 实现了 60% UI 组件的纯 Kotlin 组合封装实现,不需要 Native 提供原子控件

所以基于上面的内容,我们再来看 Kuikly UI 官方提供的结构图,是不是就清晰了很多:

Core 模块提供了统一的 UI 逻辑实现和 API 接口

  • Render 模块负责在 Android、iOS、HarmonyOS、H5 以及各种小程序等多个平台上实现 UI 的渲染 。

  • 另外在 Kuikly 领域,还有一套名为 KuiklyBase 服务,它是独立于 Kuikly UI 之外,为 Kuikly 提供基础设施支持,比如为 iOS、Android 和鸿蒙三大移动平台提供了统一的底层基建能力:

    KuiklyBase 强调在不同平台之间实现高性能的逻辑共享 ,它更像是 KMP 的进一步定制,KuiklyBase 兼容标准的 Kotlin Multiplatform 组件,允许复用成熟的 KMP 组件,比如有些业务各端都已经有 UI 层的实现,仅仅需要非 UI 的业务逻辑实现跨端,而通过 KuiklyBase 的基础设施,也可以满足这种场景的需求。

    另外 KuiklyBase 还提供了对 HarmonyOS 平台的全面支持,包括 KN HarmonyOS 编译、调试和构建能力。

    ❝ 也就是 Kuikly 在鸿蒙有支持 Kotlin Native 高性能版本。

    同时,KuiklyBase 还提供了强大的多线程和协程能力,支持复杂业务逻辑的跨平台并行处理,以满足高性能场景的需求。

    并且在开发工具链方面,KuiklyBase 覆盖了从脚手架搭建到调试、构建、发布和监控的整个流程,特别是支持和 Bugly 和 Shiply 联动提供配套能力。

    最后,KuiklyBase 还内置了性能优化工具,并针对 HarmonyOS 和 iOS 提供了优化的调试体验 。

    ❝ 目前使用 KuiklyBase 业务的团队:腾讯视频、浏览器、新闻、输入法、理财通····

    当然,这里需要注意的是, KuiklyBase 和 KuiklyUI 一起使用,某种情况下会存在场景冲突:

    • KuiklyUI 的 iOS 和鸿蒙动态化方案主要利用了 Kotlin/JS 编译成 js 产物,动态下发到宿主的js引擎去执行

    • KuiklyBase 利用 Kotlin/Native 编译成高性能的二进制产物执行,因此没有解耦 KuiklyBase 的 KMP 组件,在 iOS 和鸿蒙在动态化场景需要注意兼容

    所以,动态化决定了你优先使用哪个支持:

    • 无动态化诉求场景:KuiklyBase + KuiklyUI = 完美

    • 有动态化诉求场景:KuiklyBase 兼容 js 动态化方案还没完成,短期方案可利用 KuiklyUI 的 Module 方案来作为替代

    上面问题的核心其实是,KuiklyBase 组件因为是 KMP 组件,没有和平台做解耦,动态化时产物会运行在 js 环境中,由于 js 单线程,无法直接提供平台能力等的限制,所以决定了动态化部分不能直接使用多线程和平台能力。

    所以业务在开发过程中需要特别注意在调用平台 KMP 组件能力的时候,需要通过 Kuikly Module 方式进行解耦调用,避免直接依赖

    ❝ Kuikly 作为一个跨端的 UI 框架, 他本身不具备调用平台 API 的能力, 但是Kuikly提供了一套Module机制,可以通过Module机制将平台的 API 暴露给 Kuikly侧调用,同时 Kuikly内置了一些通用的 Module, 如果这些 Module不满足 业务诉求时, 可以通过扩展原生 API 自定义Module, 将更多的宿主平台 API 暴露给 Kuikly侧使用。

    在 KuiklyUI 内部,模块页面分为两种类型:可动态化类型(内置和动态灵活切换)和纯内置类型(只能内置) :

    而可动态化类型部分:

    • 不可直接依赖平台能力

    • 不可使用多线程和协程

    • 不可依赖内置部分

    • 不可依赖使用到了平台能力或多线程协程等能力的 KMP 组件,如果无法避免需要使用相关能力,就需要前面提到额 Kuikly Module 进行解耦调用

    ❝ 核心就是,动态化的只能是 JS 。

    最后,以下是 Kuikly 工程的项目结构说明:

    .
    ├── core                    # 跨平台模块,实现各个平台响应式 UI、布局算法、Bridge 通信等核心能力
      ├── src
        ├── commanMain            # 跨平台共享代码、定义跨平台接口 
        ├── androidMain           # Android 平台实现代码 (aar)
        ├── jvmMain               # 泛 JVM 平台代码(不涉及 Android API)(jar)
        ├── iosMain               # iOS 平台实现代码(framework)
    ├── core-render-android    # android 平台的渲染器模块
    ├── core-render-ios        # iOS 平台的渲染器模块
    ├── core-annotations       # 注解模块,定义业务注解 @Page
    ├── core-ksp               # 注解处理模块,生成 Core 入口文件 
    ├── buildSrc               # 编译脚本,用于编译、打包、分包产物相关脚本
    ├── demo                   # DSL 示例代码 
    ├── androidApp             # Android 宿主壳工程
    └── iosApp                 # iOS 宿主壳工程

    还有需要注意的是,之前的 Kuikly 的插件还不支持 K2 模式,所以如果你的 IDE 是 K2 模式,需要关闭 K2 才能支持插件

    而一天之后,已经是 1.0.3 版本,此时 KuiklyTemplate 插件也支持了最新的 K2 模式:

    另外,Kuikly 未来也会兼容 Compose DSL ,但是大概率不会是原本的 Compose ,而是类 Compose 的代码组织方式。

    ❝ 另外,在混合开发领域,在原有 App 集成 Kuikly ,可以把它简单当作如系统 webview 的概念来使用,但是如果在原生列表中嵌入 Kuikly view,目前会因为 Kuikly 本身的异步机制,导致无法同原生列表其它卡片同时生存layout和view结果,造成显示上的不同步。

    可以看到,Kuikly 总得来说还是一个类 RN 框架,但是它又不像 RN 一样的运行时 OEM 原生控件,而是在编译成完成转化为原生代码,并且它抽象出了统一的 「薄原生层」,让大量高阶控件在共享的 Kotlin 层完成实现,只让少量 native 层提供原子组件能力,从而尽可能实现 UI 的多端统一,类似于把原生控件单做 “Canvas" 效果使用。

    ❝ 总的来说,Kuikly 既能实现接近原生的性能体验和原生的开发体验,又能提供良好的动态化能力,看起来还是不错的选择。

    最后,官方表示 Kuikly 对于 Android 的同学家基本没有学习成本,只要使用过响应式开发的都能上手,而对于 iOS 同学而已,大概就是需要熟悉一下 Kotlin 语法,不过 Kotlin 和 Swift 相近度挺高,所以上手也不会太困难。

    目前 Kuikly 已经在 QQ、QQ音乐、QQ浏览器、腾讯新闻、搜狗输入法、应用宝、全民K歌、酷狗音乐、酷我音乐、自选股、ima.copilot、微视等多款产品中使用,那么,你觉得你会愿意尝试 Kuikly 吗?

    • https://kuikly.tds.qq.com/

    • https://github.com/Tencent-TDS/KuiklyUI/