Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: kuikly-compose-interop-dsl description: "Compose DSL 混用 Kuikly DSL 完整开发助手。指导如何在 Compose DSL 页面中嵌入 Kuikly DSL 组件(DeclarativeBaseView / ViewContainer)及在 Compose 中调用 Kuikly Module。当用户需要在 Compose 页面中复用 Kuikly DSL 组件、封装原生 View 为 Composable、在 Compose 中调用 Kuikly Module时使用。"
Compose DSL 混用 Kuikly DSL 组件
⚠️ 注意:本 skill 仅适用于 Compose DSL 中混用 Kuikly DSL(即在 Compose 页面中嵌入 Kuikly DSL 组件),不支持反向在 Kuikly DSL 中混用 Compose DSL。
Contents
- ComposeContainer 页面搭建
- MakeKuiklyComposeNode API(原子 / 容器)
- 关键约束与常见错误
- Compose 中使用 Kuikly Module
- 详细参考文档
ComposeContainer 页面搭建
Compose 页面继承 ComposeContainer(即 Pager),在 willInit() 中调用 setContent {}:
import com.tencent.kuikly.compose.ComposeContainerimport com.tencent.kuikly.compose.setContentimport com.tencent.kuikly.core.annotations.Page@Page("myPage")class MyPage : ComposeContainer() {override fun willInit() {super.willInit()setContent { MyScreen() }}}
ComposeContainer 继承自 Kuikly Core 的 Pager,拥有统一的跨端页面生命周期(willInit / created / pageDidAppear / pageDidDisappear / pageWillDestroy)。
MakeKuiklyComposeNode API
桥接入口,将 Kuikly DSL 组件嵌入 Compose 渲染树。两个重载:
原子组件(无子节点)
适用于 DeclarativeBaseView 子类(Video、地图等自渲染组件):
@Composablefun <T : DeclarativeBaseView<*, *>> MakeKuiklyComposeNode(factory: () -> T,modifier: Modifier,viewInit: T.() -> Unit = {}, // 创建时调用一次viewUpdate: (T) -> Unit = {}, // 每次重组时调用measurePolicy: MeasurePolicy = KuiklyDefaultMeasurePolicy)
最小示例(封装 VideoView):
import androidx.compose.runtime.Composableimport com.tencent.kuikly.compose.extension.MakeKuiklyComposeNodeimport com.tencent.kuikly.compose.ui.Modifierimport com.tencent.kuikly.core.views.VideoPlayControlimport com.tencent.kuikly.core.views.VideoView@Composablefun Video(src: String, playControl: VideoPlayControl, modifier: Modifier = Modifier) {MakeKuiklyComposeNode<VideoView>(factory = { VideoView() },modifier = modifier,viewInit = { getViewAttr().run { src(src); playControl(playControl) } },viewUpdate = { it.getViewAttr().run { src(src); playControl(playControl) } },)}
容器组件(有子节点)
适用于 ViewContainer 子类,可挂载 Compose 子节点:
@Composablefun <T : DeclarativeBaseView<*, *>> MakeKuiklyComposeNode(factory: () -> T,modifier: Modifier,content: @Composable () -> Unit, // 子内容插槽viewInit: T.() -> Unit = {},viewUpdate: (T) -> Unit = {},measurePolicy: MeasurePolicy = DefaultColumnMeasurePolicy)
最小示例(封装容器卡片):
import com.tencent.kuikly.core.base.ViewContainerimport com.tencent.kuikly.core.base.ContainerAttrimport com.tencent.kuikly.core.base.Eventimport com.tencent.kuikly.core.base.ViewConstclass KuiklyCard : ViewContainer<ContainerAttr, Event>() {override fun createAttr() = ContainerAttr()override fun createEvent() = Event()override fun viewName() = ViewConst.TYPE_VIEWfun setup(cornerRadius: Float = 12f, onClick: (() -> Unit)? = null) {attr { borderRadius(cornerRadius) }onClick?.let { event { click { onClick() } } }}}@Composablefun KuiklyCard(modifier: Modifier = Modifier,cornerRadius: Float = 12f,onClick: (() -> Unit)? = null,content: @Composable () -> Unit,) {MakeKuiklyComposeNode<KuiklyCard>(factory = { KuiklyCard() },modifier = modifier,viewInit = { setup(cornerRadius, onClick) },viewUpdate = { it.setup(cornerRadius, onClick) },content = content,)}
关键约束与常见错误
factory 基类选择
| 场景 | 基类 | |
|---|---|---|
| 原子组件(无子节点) | DeclarativeBaseView | |
| 容器组件(有子节点) | ViewContainer | |
| ❌ 禁止 | ComposeView |
❌ 禁止将 ComposeView 子类传入 factory
ComposeView 的扁平化优化导致布局 frame 丢失,视图不可见:
// ❌ 编译通过但运行时不可见class MyView : ComposeView<ComposeAttr, ComposeEvent>() { ... }MakeKuiklyComposeNode<MyView>(factory = { MyView() }, ...)// ✅ 原子组件用 DeclarativeBaseView// ✅ 容器组件用 ViewContainer
viewUpdate 必须同步更新
viewInit 只在创建时调用一次;随 Compose 状态变化的属性和事件回调必须在 viewUpdate 中也设置,否则重组后不更新。
Compose 中使用 Kuikly Module
通过 LocalActivity.current.getPager() 获取 Pager 实例,再调用 acquireModule:
import com.tencent.kuikly.compose.ui.platform.LocalActivityimport com.tencent.kuikly.core.pager.Pagerimport com.tencent.kuikly.core.module.RouterModule@Composablefun MyScreen() {val pager = LocalActivity.current.getPager() as Pagerval router = pager.acquireModule<RouterModule>(RouterModule.MODULE_NAME)// 使用 router.openPage("targetPage", params) / router.closePage() 等}
acquireModule找不到时抛异常;getModule找不到时返回 null。
详细参考
- 组件封装详解(原子/容器、viewInit vs viewUpdate、错误排查):COMPONENT_WRAPPING.md
- Module 使用详情(Router / Notify / SP / PageData / 自定义 Module):MODULE_USAGE.md