Kuikly是腾讯基于 Kotlin Multiplatform(KMP) 构建的跨平台 UI 框架,一套代码可覆盖 Android、iOS、HarmonyOS、H5、微信小程序和 MAC。得益于 Kotlin/Native 编译产物直接对接原生渲染管线,Kuikly 本身已具备原生级性能。
但在首屏打开链路上——容器初始化 → 运行时准备 → 业务代码执行 → 数据请求 → 布局测量 → 节点构建 → 上屏——任何一环的耗时都会变成用户可感知的白屏等待。单纯让"代码跑得更快"已逼近收益天花板,要从根本上加速,必须从渲染链路的调度方式入手。
为此 Kuikly 推出了自研首屏加速方案 TurboDisplay,在页面二次打开场景下实现"打开即可见、可交互",已在 QQ 游戏、搜狗输入法、腾讯地图等产品中取得 60%~80% 的首屏耗时优化。
一、为什么传统优化做不到"秒开"
业界常见的手段各有局限:
| 方案 | 作用 | 不足 |
|---|---|---|
| Bitmap / 截图占位 | 立即给视觉反馈 | 不可滚动、不可交互,非真实页面 |
| 接口数据缓存 | 省去网络等待 | 不覆盖业务执行、布局测量、节点构建 |
| Skeleton / Loading | 缓解焦虑感 | 没有缩短可交互时间 |
真正的"秒开"要求缓存对象不只是图片或数据,而是框架渲染产物本身——已构建好的渲染节点树,下次打开直接呈现可交互内容。这就是 TurboDisplay 的设计起点。
二、为什么简单的"节点直出"还不够
最直观的思路是把渲染节点树序列化落盘,下次打开反序列化直接重建视图,跳过"执行业务代码 → 布局测量 → 节点构建"。
但这只能缩短跨端侧业务执行时间,前置的引擎/容器初始化仍无法省略,首屏还是会受阻塞。且缓存恢复仍嵌套在原执行链路中——本质上只是"跑得快一点",并没有重构链路。
TurboDisplay 的核心改进是:把缓存恢复从主链路中拆出,形成独立快速路径,并与原执行链路并行工作。
三、TurboDisplay 三大核心机制
3.1 双线并行
容器及根 View 构建完成后:
- 端侧快速路径:立即读取本地缓存 → 反序列化为节点树 → 发渲染指令 → 首屏直出;
- 跨端侧后台路径:照常执行真实页面的业务逻辑、布局测量、节点构建,生成真实节点树;
- 后台完成后与缓存节点树做 diff,将差异增量更新到屏幕上。
这样用户第一时间看到可交互的首屏,后台逻辑不影响展示时机。
3.2 节点采集
TurboDisplay 缓存的是端侧节点树上完整节点信息:
- 节点属性(颜色、字号、可见性等)
- 绑定事件(点击、滑动)
- 布局 Frame、Shadow 信息
- 节点方法调用、树结构变化
采集时自动比对缓存首屏与真实首屏的树差异,限频写盘。业务可配置是否捕获结构差异,在缓存体积与新鲜度间取舍。
3.3 增量更新
为避免真实页面覆盖缓存时产生闪屏或跳变,TurboDisplay 采用局部 diff 更新:
- 跨端侧构建真实节点树后与缓存树比对属性 / Frame / 方法参数差异
- 全量回放首屏期间暂存的交互事件
- 仅新建缺失节点,不做整体替换
实现缓存首屏 → 真实首屏的无感平滑切换。
四、状态恢复与延迟 Diff
实际场景中用户可能已滚动列表或触发交互,缓存首屏处于非默认状态,而跨端侧构建的真实页仍在默认位置。若直接 diff,"端侧交互态 vs 默认态"的差异会导致首屏被强制重置回默认——表现为位置跳变。
TurboDisplay 的解法是由跨端侧调度 Diff 时机:在生成渲染指令前,先将滚动偏移量、暂存交互事件应用到真实页节点,使两端对比基准一致,再执行 diff。此时非默认内容不再是差异项,不会被错误覆盖。
五、性能数据
实验室测试(页面二次打开):iPhone 13 Pro Max / iPhone 7 Plus 均实现首帧即现。
线上业务数据(逻辑与数据均已本地缓存,无网络耗时):
| 业务页面 | 优化前(ms) | 优化后(ms) | 降幅 |
|---|---|---|---|
| 腾讯地图-页面A | 281 | 48 | 82.9% |
| QQ游戏-页面B | 146 | 40 | 72.6% |
| QQ游戏-页面C | 116 | 32 | 72.4% |
| 输入法-页面A | 126 | 42 | 66.7% |
| 输入法-页面B | 54 | 17 | 66.7% |
六、接入方式
TurboDisplay 设计为业务无侵入,Native 容器侧仅需实现一个 Key 接口即可开启:
// iOS KuiklyRenderViewController
- (NSString *)turboDisplayKey {
return @"pageName"; // 返回唯一页面标识
}
Kotlin 侧可通过 turboDisplayConfig()设置 KRTurboDisplayConfig.turboDisplayKey。
七、小结
TurboDisplay 的本质是渲染节点缓存 + 端侧直出 + 双线程并行 + 延迟 Diff,跳出"优化执行速度"的思维定势,从链路调度层面实现二次打开秒开。目前主要覆盖二次打开场景,首次打开加速(编译期首屏提取 + 微指令引擎)也在规划中。
- 📦 GitHub:github.com/Tencent-TDS…
- 📚 官方文档:kuikly.tds.qq.com/
- ✅ 原文:跨端页面秒开,腾讯开源框架Kuikly是怎么做到的?