mcpField
C
compose-skill

compose-skill

github.com/meet-miyani开发306191 次安装6 天前更新
代码仓库

关于 compose-skill

面向 Jetpack Compose 与 Compose Multiplatform 开发的技能指南,涵盖应用架构、状态管理、UI 和跨平台实践。它强调遵循现有项目约定,并在推荐依赖前核实目标平台与 API。

主要功能

  1. 01MVI 与 MVVM 架构指导
  2. 02状态和副作用建模
  3. 03Compose UI 边界与最佳实践
  4. 04跨平台代码共享建议
  5. 05依赖坐标与目标支持核验

适用场景

  1. 01为新 Compose 屏幕设计状态与事件流
  2. 02排查可组合函数中的业务逻辑或状态问题
  3. 03评估依赖是否支持所需平台
  4. 04规划 Compose Multiplatform 的代码划分

MCP 相关

指南建议在可用时使用文档 MCP 工具查询依赖文档,并要求调用前确认工具名称和参数。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/meet-miyani/compose-skill --skill compose-skill

安装后在 Claude Code 中输入/compose-skill确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.gitignore
LICENSE
README.md
.cursor/rules/
reference-file-standards.mdc
.github/workflows/
release.yml
validate.yml
agents/
openai.yaml
references/
accessibility.md
animations-advanced.md
ci-cd-distribution.md
animations.md
coroutines-flow-advanced.md
compose-essentials.md
clean-code.md
architecture.md
cross-platform.md
anti-patterns.md
datastore.md
dependency-injection.md
coroutines-flow.md
image-loading.md
hilt.md
ios-swift-interop.md
material-design.md
lists-grids.md
gradle-build.md
mvvm.md
koin.md
navigation-2-di.md
navigation-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 代码时,请遵循以下流程:

  1. 先阅读现有代码,了解上下文——检查约定、基类和布局。对于简单的 UI 或逻辑需求,只需阅读直接相关的文件,以节省时间。除非用户要求进行结构性重构,否则不要梳理整个项目架构。
  2. 识别问题类型——这是架构、状态建模、性能、导航、DI、动画、跨平台还是测试相关的问题?
  3. 应用以下核心规则——本文件中的决策启发式和默认做法涵盖了大多数情况。
  4. 查阅合适的参考资料——只有在需要更深入的指导时,才从 references/ 加载相关文件。使用详细参考资料部分的快速路由来选择合适的文件。
  5. 推荐前先验证依赖——添加或升级任何依赖之前,请通过文档 MCP 工具或官方文档验证坐标、目标平台支持情况和 API 形式(参见依赖验证规则)。
  6. 结合上下文指出反模式——如果用户的代码违反最佳实践,请在面向生产环境的代码中指出。对于快速原型或细微的 UI 调整,应优先回答具体问题,而不是讲解严格规则。
  7. 编写最精简且正确的解决方案——不要过度设计。优先采用特性专用代码,而不是通用框架。

依赖验证规则

推荐任何新依赖或版本升级前,请先验证:

  1. 坐标 — 确认确切的 Maven 坐标(group:artifact:version)存在且为当前版本。
  2. 目标平台支持 — 确认该构件支持项目的目标平台(Android、iOS、Desktop、commonMain)。除非经过验证,否则不要假设 Jetpack 库可用于 commonMain。
  3. API 形式 — 确认计划使用的 API 在该版本中确实存在。函数签名、参数名称和返回类型可能会随主版本变化。

验证方式:

  • 文档 MCP 工具(首选)— 如果有可用的文档 MCP 服务(例如 Context7),请先验证确切的工具名称和参数架构,再使用它获取该库当前的官方文档。
  • 官方文档 — 搜索该库的官方文档或发行说明。
  • Maven Central / Google Maven — 检查构件是否可用以及支持的平台。

如果无法验证(没有文档工具、无法访问网络或文档不可用),仍请提供标准依赖片段或最新已知的依赖片段。 添加简短注释(例如 // Verify latest version),以免阻碍用户继续操作。

获取最新文档

添加新依赖、升级主版本或验证最新 API 用法时,如果有可用的文档 MCP 工具(例如 Context7),请使用它。调用前,请验证工具的确切名称和参数架构——不同环境中的工具名称可能不同。

  1. 解析库 ID — 如果工具要求先进行解析,请先调用它。
  2. 查询文档 — 使用已解析的 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 基类或模式,就使用它,不要再引入与之竞争的抽象

状态建模

对于计算器/表单屏幕,将状态拆分为四类:

  1. 可编辑输入 — 用户编辑时的原始文本和选项值
  2. 派生的显示/业务数据 — 解析、验证、计算后的值
  3. 已持久化的领域快照 — 用于脏数据跟踪或重置的已保存实体
  4. 仅供临时 UI 使用的数据 — 纯视觉数据,不涉及业务
关注点位置示例
原始字段文本state 字段"12"、"12."、""
解析/派生数据state 计算属性或字段val hasRequiredFields: Boolean
验证state.validationErrors 或类似位置mapOf("name" to "Required")
加载/刷新state 标志isSaving = true
一次性 UI 命令通过 Channel 发送的 EffectSnackbar、导航、分享
滚动/焦点/动画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 设置),才加载恰好一个参考文件。 从下方选择合适的文件——不要臆测性地加载文件。

快速路由

验证

运行 ./scripts/validate.sh,根据 agentskills.io 规范 检查技能包。该脚本会检查令牌预算、失效链接、文件结构和内容质量。提交前请修复所有错误。

评论

支持 Markdown