Jetpack Compose 大家都熟,声明式 UI,写起来确实爽。但你有没有想过一个问题------Compose 算完的那棵 UI 树,到底是怎么落到真正的屏幕上的?
在 Android 上,这事由 Android UI 系统接手。可如果你要跨平台呢?比如 KuiklyUI 这套自研的跨端方案,它想用标准的 Compose 来写界面,但渲染走自己的 Core + Bridge + Render 链路------那 Compose 算好的结果,要怎么交给它?
说白了,这中间需要一个翻译官。KuiklyUI 的做法是搞了一个叫 Applier 的东西。
讲道理,KuiklyUI 并没有重新发明一套 Compose DSL。你在页面上写的 @Composable、remember、mutableStateOf,全特么是标准 Compose API。State 变了之后的重组调度 和Composition 记录,也直接复用 Compose Runtime。
那 KuiklyUI 管什么?它管树算出来之后的落地。
你看,Compose Runtime 只负责计算------它知道哪些节点该插、该删、该移,但它完全不管这些结果落到哪个渲染宿主上。Android 有 Android 的接法,KuiklyUI 有自己的接法。
KuiklyUI 这边,Core 维护一棵平台无关的 view 树,Frame 记位置和尺寸,Attr 管透明度、圆角这些视觉属性,Bridge 把创建和更新指令派发给各平台的 Render。你把这三层想象成一个流水线就行。
那 Compose 上层的树,怎么流进这条流水线?答案就在 ComposeContainer + KuiklyApplier + KNode 这三兄弟身上。

ComposeContainer:入口
页面进来先找 ComposeContainer。它是 Pager 的子类,所以 KuiklyUI 那套路由、生命周期、页面尺寸什么的,Compose 页面也都用得上。
容器会准备好一棵根 DivView,当作 Compose 子树在 Core 里的挂载点。然后把页面的尺寸喂给 Compose Scene,Scene 推进重组、布局和绘制,帧循环还在 KuiklyUI 的调度体系里跑。
好,入口有了,接下来是树的变化怎么落地。
KuiklyApplier:树变化的搬运工
Compose 重组之后,会产出一组树操作------哪个节点要插入,哪个要挪位置。它自己不动手,而是交给 Applier。
KuiklyApplier 继承的是 Compose Runtime 的 AbstractApplier,它只负责一件事:把树操作转交出去。不参与布局,不处理绘制,不跟 Bridge 通信。
那转交给谁?交给当前关联的 KNode。
KNode:关键先生
KNode 才是真正干活的那个。它干了两件事:
第一,继承 Compose UI 层的 LayoutNode,参与 Compose 的布局和绘制计算。第二,持有 KuiklyUI 的 DeclarativeBaseView,能把结构变化写进 Core view 树。
所以你看到了,节点映射的活儿基本都在 KNode 身上,KuiklyApplier 只是个传话的。
结构搭好之后,Compose 还会算出位置、尺寸和绘制属性。这些数据进了 KNode,会被按 Frame 和 Attr 的边界拆开:
-
• 布局结果 → Frame:KNode 拿到 Compose 算出来的位置和尺寸,按页面 density 换算,然后更新 RenderView。RenderView 是 Core 里跟平台实际渲染对象对应的东西。
-
• 绘制结果 → Attr:KNode 在绘制过程中收集透明度、圆角、裁剪这些属性,攒成 Attr 更新,再由 Bridge 下发给各平台 Render。

你懂的,这里有个天然的边界问题------Compose 的某个效果能不能正常落地,取决于 KuiklyUI 那端有没有对应的几何或属性表达。两边表达能力对不上的时候,适配层就得补转换逻辑或者保留限制。
维护边界在哪
总结下来,Compose 的计算(Runtime、Composition、重组机制)由标准 Compose 提供。KuiklyUI 沿用 Pager、Core、Bridge 和各平台 Render。中间那层适配代码,集中在 ComposeContainer、KuiklyApplier 和 KNode 三个组件上。
KNode 的职责最重------它既要守 Compose 的节点和布局语义,又要维护 Core view、Frame、Attr 的映射。
日常加新 Compose 能力的时候,顺着这个思路判断就行:先看影响的是树结构、几何信息还是视觉属性,再查 KuiklyUI 下游能不能表达这份结果。
我个人觉得这套方案挺漂亮的。Compose Runtime 这层抽象本身够干净,KuiklyUI 没去动它,而是在接缝处做适配,两边各司其职。比起那种在 DSL 层硬造一套"自研 Compose"的搞法,明显省心多了。
你们项目里有用 Compose Multiplatform 做跨端的吗?遇到哪些坑?评论区聊聊。