第 9 章 · 动态化 & 性能 — 启动优化 / 帧率诊断 / 包体瘦身

点击「触发动态加载」看模块下发流程;切换 FPS 模拟器观察帧率监控效果

Kuikly 动态化整体思路

工程拆分

Project/
├── app/                 ← 宿主壳工程(必须发版)
│   └── KuiklyApplication
├── shared-base/         ← 必须内置在 App 的基础模块
│   └── User / Theme / 基础 Module
└── shared-business/     ← 可动态下发的业务模块
    ├── home/            ← 独立 dex/aar
    ├── detail/
    ├── publish/
    └── activity/        ← 最常变

动态加载流程模拟

--:--:--等待操作…

各端动态化能力对比

平台产物限制
Androiddex / aar几乎无限制(自定义 ClassLoader)
iOSKMP 字节码 + 解释器Apple 审核:不能下发可执行代码
HarmonyOSso依赖系统能力支持
Web / 小程序js bundle同 Web 标准

启动各阶段拆解

T0 → T1: Application.onCreate

SDK 初始化 + Module 注册 + 全局 Store 初始化

T1 → T2: MainActivity.onCreate

触发 KuiklyCoreEntry.triggerRegisterPages → 启动 KuiklyActivity

T2 → T3: Pager.created → body()

构建 BuildTree → diff RenderTree

T3 → T4: 渲染指令执行

原生层创建 View,屏幕首次刷新(first paint)

T4 → T5: pageDidAppear

数据加载、入场动画、PV 埋点

T5 → T6: 数据完成

用户能看到完整内容(first meaningful paint)

5 招优化术

① 骨架屏:先渲染再加载

if (ctx.firstLoading) {
    renderSkeleton().invoke(this)     // 骨架屏立即渲染
} else {
    renderRealContent().invoke(this)
}

② SDK 延迟初始化

class KuiklyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        ModuleRegistry.register("Toast") { ToastModule() }   // 启动必需

        Handler(Looper.getMainLooper()).postIdle {            // 延后到 idle
            ModuleRegistry.register("Camera") { CameraModule() }
            ModuleRegistry.register("Push") { PushModule() }
        }
    }
}

③ 拆 body:折叠以下延后挂

override fun body() = {
    renderHero(ctx).invoke(this)             // 首屏,立即渲染

    if (ctx.deferredLoaded) {                 // 折叠以下,pageDidAppear 后再挂
        renderRecommend(ctx).invoke(this)
        renderComments(ctx).invoke(this)
    }
}

帧率诊断

Kuikly 提供帧监控 API:

acquireModule<DeviceInfoModule>(...).addFrameRateListener { fps ->
    if (fps < 50f) KLog.w("Perf", "Low fps: $fps")
}

FPS 模拟器

60 FPS
最近 30 帧

列表卡顿 3 大元凶

元凶表现解法
item 渲染太重滚动卡,每个 item 创建慢简化 item 布局,抽公共组件
observable 颗粒度太粗一字段变化引起整 List 刷按 item 粒度拆 observable
主线程被堵图片同步解码 / 网络回调直接刷 UI用 Image 组件,回调 dispatchers.Main

优化前后对比

❌ 优化前

item 嵌套层数6 层
滚动 fps30-40
主线程占用90%
内存峰值800MB(崩溃)

✅ 优化后

item 嵌套层数2-3 层
滚动 fps60
主线程占用30%
内存峰值50MB

内存优化

Pager 内存泄漏 4 大原因

原因解法
NotificationListener 没解绑pageWillDestroy 里 removeNotificationListener
Timer 没 cancelpageWillDestroy 里 timer.cancel(taskId)
全局 Store 持有 Pager 引用避免 GlobalStore.currentPage = this
图片缓存爆炸LRU 限制大小(框架默认有)

包体优化(Android)

招数说明
1. 只打必要 ABIarmeabi-v7a + arm64-v8a 即可
2. 启用 R8/ProGuard去除未使用代码,平均 30% 减包
3. 大图放 CDN不打进 APK
4. 业务模块走动态化非核心页面下发
5. 资源压缩 + WebPPNG → WebP 平均省 30%

Kuikly vs RN vs Flutter(QQ 浏览器实测)

首屏渲染时间

RN
800ms
Flutter
600ms
Kuikly
480ms
最快

滚动帧率(千条数据)

RN
45fps
Flutter
58fps
Kuikly
60fps
满帧

SDK 包体(Android)

RN
+3MB
Flutter
+5MB
Kuikly
+0.4MB
最小

内存(千条信息流)

RN
120MB
Flutter
150MB
Kuikly
80MB
最低

数据来源:腾讯官方 2025 年公布。Kuikly 在「包体 + 内存」上的优势明显,符合"原生渲染 + KMP 编译"的架构特点。