关于 compose-skill
面向 Jetpack Compose 与 Compose Multiplatform 开发的技能指南,涵盖应用架构、状态管理、UI 和跨平台实践。它强调遵循现有项目约定,并在推荐依赖前核实目标平台与 API。
主要功能
- 01MVI 与 MVVM 架构指导
- 02状态和副作用建模
- 03Compose UI 边界与最佳实践
- 04跨平台代码共享建议
- 05依赖坐标与目标支持核验
适用场景
- 01为新 Compose 屏幕设计状态与事件流
- 02排查可组合函数中的业务逻辑或状态问题
- 03评估依赖是否支持所需平台
- 04规划 Compose Multiplatform 的代码划分
MCP 相关
指南建议在可用时使用文档 MCP 工具查询依赖文档,并要求调用前确认工具名称和参数。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meet-miyani/ compose-skill --skill compose-skill安装后在 Claude Code 中输入/compose-skill确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoreLICENSEREADME.md.cursor/rules/reference-file-standards.mdc.github/workflows/release.ymlvalidate.ymlagents/openai.yamlreferences/accessibility.mdanimations-advanced.mdci-cd-distribution.mdanimations.mdcoroutines-flow-advanced.mdcompose-essentials.mdclean-code.mdarchitecture.mdcross-platform.mdanti-patterns.mddatastore.mddependency-injection.mdcoroutines-flow.mdimage-loading.mdhilt.mdios-swift-interop.mdmaterial-design.mdlists-grids.mdgradle-build.mdmvvm.mdkoin.mdnavigation-2-di.mdnavigation-3-di.md详细介绍
Jetpack Compose 与 Compose Multiplatform
本技能涵盖 Compose 应用开发的完整生命周期——从架构和状态管理,到 UI、网络、持久化、性能、无障碍、跨平台共享、构建配置和分发。Jetpack Compose 和 Compose Multiplatform 共享相同的核心 API 和思维模型。并非所有 Jetpack 库都能在 commonMain 中使用——许多库仍仅支持 Android。现在有一部分 AndroidX 库已发布多平台制品(例如 lifecycle-viewmodel、lifecycle-runtime-compose、datastore-preferences),但具体支持情况和 API 范围会因版本而异。向 commonMain 添加任何 Jetpack/AndroidX 依赖之前,请先查看 Maven Central 或库的官方文档,确认该制品已针对所有必需目标平台发布。 CMP 使用 expect/actual 或接口处理平台专属代码。MVI(Model-View-Intent)是推荐采用的架构,但本技能也会适配现有项目约定。
现有项目策略
不要强行迁移。 如果项目已采用 MVI 并遵循自身约定(例如使用不同的基类、命名方式或文件布局),请予以尊重。根据项目现有模式进行适配。重要的是架构模式——使用 Event、State 和 Effect 实现单向数据流,而不是特定的基类或框架。只有在用户提出要求,或现有代码存在明显的架构问题(例如在可组合项中编写业务逻辑、状态变更散乱等)时,才建议进行结构调整。
工作流
协助编写 Jetpack Compose 或 Compose Multiplatform 代码时,请遵循以下流程:
- 先阅读现有代码,了解上下文——检查约定、基类和布局。对于简单的 UI 或逻辑需求,只需阅读直接相关的文件,以节省时间。除非用户要求进行结构性重构,否则不要梳理整个项目架构。
- 识别问题类型——这是架构、状态建模、性能、导航、DI、动画、跨平台还是测试相关的问题?
- 应用以下核心规则——本文件中的决策启发式和默认做法涵盖了大多数情况。
- 查阅合适的参考资料——只有在需要更深入的指导时,才从
references/加载相关文件。使用详细参考资料部分的快速路由来选择合适的文件。 - 推荐前先验证依赖——添加或升级任何依赖之前,请通过文档 MCP 工具或官方文档验证坐标、目标平台支持情况和 API 形式(参见依赖验证规则)。
- 结合上下文指出反模式——如果用户的代码违反最佳实践,请在面向生产环境的代码中指出。对于快速原型或细微的 UI 调整,应优先回答具体问题,而不是讲解严格规则。
- 编写最精简且正确的解决方案——不要过度设计。优先采用特性专用代码,而不是通用框架。
依赖验证规则
推荐任何新依赖或版本升级前,请先验证:
- 坐标 — 确认确切的 Maven 坐标(
group:artifact:version)存在且为当前版本。 - 目标平台支持 — 确认该构件支持项目的目标平台(Android、iOS、Desktop、
commonMain)。除非经过验证,否则不要假设 Jetpack 库可用于commonMain。 - API 形式 — 确认计划使用的 API 在该版本中确实存在。函数签名、参数名称和返回类型可能会随主版本变化。
验证方式:
- 文档 MCP 工具(首选)— 如果有可用的文档 MCP 服务(例如 Context7),请先验证确切的工具名称和参数架构,再使用它获取该库当前的官方文档。
- 官方文档 — 搜索该库的官方文档或发行说明。
- Maven Central / Google Maven — 检查构件是否可用以及支持的平台。
如果无法验证(没有文档工具、无法访问网络或文档不可用),仍请提供标准依赖片段或最新已知的依赖片段。 添加简短注释(例如 // Verify latest version),以免阻碍用户继续操作。
获取最新文档
添加新依赖、升级主版本或验证最新 API 用法时,如果有可用的文档 MCP 工具(例如 Context7),请使用它。调用前,请验证工具的确切名称和参数架构——不同环境中的工具名称可能不同。
- 解析库 ID — 如果工具要求先进行解析,请先调用它。
- 查询文档 — 使用已解析的 ID 和具体问题进行调用。
替代方式:用户可以在提示词中添加 use context7(或同等内容)。随附的参考资料仍是架构模式和 MVI 指南的主要来源;API 特定和版本特定查询则使用文档工具。
核心架构:MVI 或 MVVM
MVI 和 MVVM 都采用单向数据流:UI 渲染状态 → 用户执行操作 → ViewModel 更新状态 → UI 重新渲染。两者的区别在于 UI 操作如何传递到 ViewModel。
- MVI:
sealed interface Event+ 单一onEvent()入口 - MVVM:命名的公共函数(
onTitleChanged()、save())
两种模式都使用:
- State — 完整描述屏幕的不可变数据类,通过
StateFlow持有 - Effect — 通过
Channel传递的一次性命令(导航、Snackbar、分享)
默认建议: 如果项目现有模式清晰合理,请予以保留。对于新项目,请根据团队偏好和屏幕复杂度进行选择。决策指南请参阅 架构与状态管理,实现细节请参阅 mvi.md 或 mvvm.md。
UI 渲染边界
以下边界同时适用于 MVI 和 MVVM:
- Route 组合项:获取 ViewModel,通过
collectAsStateWithLifecycle()收集状态,通过CollectEffect收集效果(参见 compose-essentials.md),绑定导航、Snackbar 和平台 API - Screen 组合项:无状态渲染器——接收状态和回调(MVI:
onEvent,MVVM:独立回调),渲染屏幕,并为叶子组合项适配回调 - Leaf 组合项:渲染子状态,发出特定回调,仅保留少量视觉局部状态(焦点、滚动、动画)
决策启发式
- 可组合函数负责渲染状态和发出事件,绝不决定业务规则
- 如果某个值可以从状态推导出来,就不要冗余存储,除非异步处理、持久化或性能方面的需求有此必要
- ViewModel 中的事件处理负责状态转换;可组合函数不修改状态
- UI 本地状态仅适用于短暂的视觉需求:焦点、滚动、动画进度、展开开关
- 除非业务逻辑依赖动画专用标志,否则不要将其放入全局屏幕状态
- 传递给叶子可组合函数的状态应尽可能精简
- MVI:将
onEvent()作为唯一入口;MVVM:为用户操作实现具名函数 - 不要为每次仓库调用都引入一个用例
- 跨平台共享应优先考虑业务逻辑和呈现状态,其次才是平台行为
- 优先通过状态形状和读取边界减少重组,其次才考虑 Compose API
- 如果项目已有 MVI 基类或模式,就使用它,不要再引入与之竞争的抽象
状态建模
对于计算器/表单屏幕,将状态拆分为四类:
- 可编辑输入 — 用户编辑时的原始文本和选项值
- 派生的显示/业务数据 — 解析、验证、计算后的值
- 已持久化的领域快照 — 用于脏数据跟踪或重置的已保存实体
- 仅供临时 UI 使用的数据 — 纯视觉数据,不涉及业务
| 关注点 | 位置 | 示例 |
|---|---|---|
| 原始字段文本 | state 字段 | "12"、"12."、"" |
| 解析/派生数据 | state 计算属性或字段 | val hasRequiredFields: Boolean |
| 验证 | state.validationErrors 或类似位置 | mapOf("name" to "Required") |
| 加载/刷新 | state 标志 | isSaving = true |
| 一次性 UI 命令 | 通过 Channel 发送的 Effect | Snackbar、导航、分享 |
| 滚动/焦点/动画 | Compose 本地状态 | LazyListState、焦点请求器 |
推荐默认做法
除非项目已有其他一致的模式,否则请采用以下做法。
| 关注点 | 默认做法 |
|---|---|
| ViewModel | 每个屏幕一个 ViewModel(CMP 使用 commonMain,仅限 Android 的功能使用功能包)。MVI:以 onEvent(Event) 作为入口;MVVM:使用具名函数 |
| 状态唯一数据源 | 由 ViewModel 持有的 StateFlow<FeatureState> |
| 事件处理 | MVI:使用带 when 表达式的 onEvent(event);MVVM:使用具名函数。两者都会将用户操作映射为状态更新、Effect 发出和异步任务启动 |
| 副作用 | 对于由 UI 消费的一次性事件(导航、Snackbar),通过 Channel<Effect>(Channel.BUFFERED) 发送 Effect。异步工作(网络、持久化)在 viewModelScope 中启动 |
| 异步加载 | 保留先前内容,切换加载标志,取消过时的任务,并在完成后更新状态 |
| 简洁的 UI 契约 | 渲染属性、发出明确的回调,仅将短暂的视觉状态保留在本地 |
| 资源访问 | 在状态中使用语义键/枚举;在靠近 UI 的位置解析字符串/图标。CMP 使用 Res.string / Res.drawable(而非 Android R)。请参阅资源 |
| 平台分离 | CMP:在 commonMain 中共享,使用 expect/actual(通过 build.gradle.kts 核实 Kotlin 1.9 与 2.0+,或询问用户)或接口,默认使用 Koin DI。仅限 Android:使用标准包、Hilt 或 Koin DI |
| 导航 | ViewModel 发出语义化导航 Effect;由路由/导航层执行 |
| 持久化(设置) | 在 commonMain 中使用 DataStore Preferences 保存键值设置;使用 Typed DataStore(JSON)保存结构化设置对象;使用 Room 保存关系型/可查询数据。请参阅DataStore |
| 测试 | 在 commonTest 中通过 Turbine 测试 ViewModel 的事件→状态→Effect;将验证器/计算器作为纯函数测试;按目标平台测试平台绑定 |
做/不做速查表
应做事项
- 将原始可编辑文本与解析后的值分别建模
- 保持状态不可变且易于比较
- 尽可能复用未变更的嵌套对象
- 产生语义化副作用,而不是在事件处理中调用平台 API
- 刷新时保留旧内容
- 在靠近呈现层边界的位置,将领域数据映射为 UI 状态
- 使用针对特定功能的 ViewModel 名称
- 使用稳定的领域 ID 作为列表项的键
- 在文件顶部导入所有类型和函数;使用
import ... as ...别名解决名称冲突 - 避免发出无操作的状态更新(内容未变更时不要更新状态)
- 遵循项目现有的 MVI 约定
不应做事项
- 不要在可组合函数体内解析数字
- 不要从可组合函数中发起网络请求
- 不要在屏幕状态中存储
MutableState、控制器、lambda 或平台对象 - 不要在状态中用“仅消费一次”的布尔值表示 Snackbar/导航;应使用副作用
- 不要将每个细微的视觉切换都保留在 ViewModel 状态中
- 不要将整个状态传给每个子可组合函数
- 不要将每个仓库调用都封装在一个用例类中
- 刷新期间不要用全屏加载指示器覆盖整个屏幕
- 不要强行将正常运行的代码库迁移到不同的架构或基类
- 不要在代码中内联使用完全限定的包路径(例如
com.example.pkg.SomeClass.method())——始终在文件顶部导入
详细参考
基本的 Compose 用法不需要加载参考文件。 如果你已了解如何构建所需的 UI 或逻辑,请立即编写代码。仅当任务涉及高级概念时(例如 Paging 3、Nav 3 设置),才加载恰好一个参考文件。 从下方选择合适的文件——不要臆测性地加载文件。
快速路由
- 重组过于频繁、稳定性或 Compose Compiler Metrics → performance.md
- Channel 与 SharedFlow、Flow 运算符、结构化并发或异常处理 → coroutines-flow.md
- 背压、callbackFlow、Mutex/Semaphore 或 Turbine 测试 → coroutines-flow-advanced.md
- Nav 3 路由、标签页、场景、深层链接或返回栈模式 → navigation-3.md
- Nav 2 NavHost、标签页、深层链接、嵌套图或动画 → navigation-2.md
- 将 Hilt 或 Koin 与导航接线 → 根据版本参阅 navigation-3-di.md 或 navigation-2-di.md
- 从 Nav 2 迁移到 Nav 3 → navigation-migration.md
- Paging 3 配置、PagingSource、筛选器、LoadState 或转换 → paging.md
- 使用 Room 和 RemoteMediator 实现离线优先分页 → paging-offline.md
- Paging 的 MVI 集成、分页测试或分页反模式 → paging-mvi-testing.md
- Ktor 客户端配置、插件、DTO、API 服务或仓库模式 → networking-ktor.md
- 身份验证(bearer)、WebSockets 或 SSE → networking-ktor-auth.md
- 网络层架构、插件组合或错误处理策略 → networking-ktor-architecture.md
- 选择 Hilt 还是 Koin → 先参阅 dependency-injection.md,然后参阅所选框架对应的文件
- 无障碍审查、语义、触控目标或 WCAG 对比度 → accessibility.md
- 动画 API 选择(animate*AsState、Animatable、transitions、AnimatedVisibility) → animations.md
- 共享元素过渡、手势驱动动画、Canvas 或 graphicsLayer → animations-advanced.md
- 代码审查或反模式检测 → 先参阅 anti-patterns.md,再按需参阅特定领域的文件
- 向 Swift 暴露 Kotlin、SKIE 或 Flow→AsyncSequence → ios-swift-interop.md
- ViewModel 管道、状态建模、领域层或功能间通信 → architecture.md
- MVI 管道、Event/State/Effect、onEvent 模式或 Effect 交付 → mvi.md
- MVVM 管道、ViewModel 命名函数或直接回调式 UI 接线 → mvvm.md
- 文件组织、命名约定或规范的屏幕架构 → clean-code.md
- 三个阶段、状态原语、副作用或修饰符 → compose-essentials.md
- M3 主题、动态颜色、M3 组件或自适应布局 → material-design.md
- AsyncImage、图片缓存、SVG 或 Coil 3 → image-loading.md
- LazyColumn、LazyRow、键、网格、分页器或滚动状态 → lists-grids.md
- Nav 2 与 Nav 3 的选择或 MVI 导航规则 → navigation.md
- 加载状态、骨架屏/闪烁效果或行内验证 UX → ui-ux.md
- Turbine、ViewModel 测试、Macrobenchmark 或精简测试矩阵 → testing.md
- DataStore Preferences、Typed DataStore 或 KMP DataStore → datastore.md
- Room 实体、DAO、迁移、关系或 Room 的 MVI 集成 → room-database.md
- Ktor
@Resource路由或类型安全的 API 定义 → networking-ktor.md § Type-Safe Resources - MockEngine、网络测试或 Koin/Hilt 网络 DI → networking-ktor-testing.md
- Koin CMP 配置、Nav 3 Koin 集成或作用域模块 → koin.md
- Hilt Android 配置、@HiltViewModel、作用域或 Hilt 测试 → hilt.md
- commonMain 共享、expect/actual 或平台桥接 → cross-platform.md
- CMP Res 类、限定符、本地化或 Android 资源互操作 → resources.md
- AGP 9+、版本目录、约定插件或复合构建 → gradle-build.md
- GitHub Actions CI/CD、桌面端打包、签名或公证 → ci-cd-distribution.md
验证
运行 ./scripts/validate.sh,根据 agentskills.io 规范 检查技能包。该脚本会检查令牌预算、失效链接、文件结构和内容质量。提交前请修复所有错误。