ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

agentic-awesome-skills 中的 Jetpack Compose Expert 技能解析:StateFlow 状态管理、类型安全导航与重组优化的生产级实践

2026/9/20 22:05:46 拓冰建站 浏览量
agentic-awesome-skills 中的 Jetpack Compose Expert 技能解析:StateFlow 状态管理、类型安全导航与重组优化的生产级实践 agentic-awesome-skills 中的 Jetpack Compose Expert 技能解析StateFlow 状态管理、类型安全导航与重组优化的生产级实践【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,115 agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址: https://gitcode.com/gh_mirrors/an/agentic-awesome-skills本文以 agentic-awesome-skills 仓库中 android-jetpack-compose-expert 技能定义 为主体完整讲解该技能覆盖的 Compose 生产级开发套路依赖版本管理、基于StateFlow的 MVVM 状态管理、无状态组件拆分、类型安全导航以及重组recomposition性能优化与排障方法。读完本文你可以把这套技能直接交给 Claude Code / Codex 等 Agent 使用也能将其中的架构模式与代码示例独立应用到自己的 Android 工程中。技能定位它解决什么问题该技能的 frontmatter 声明如下见 SKILL.md 头部name: android-jetpack-compose-expert description: Expert guidance for building modern Android UIs with Jetpack Compose, covering state management, navigation, performance, and Material Design 3. risk: safe source: community date_added: 2026-02-27在 data/catalog.json 的目录条目中该技能被归类为mobile类别risk为safesource为community标签为[android, jetpack, compose]data/skills_index.json 进一步标注其插件分发目标为codex: supported, claude: supported且setup.type为none——即无需额外环境配置即可使用。技能正文给出的适用场景When to Use This Skill使用 Jetpack Compose 启动一个新的 Android 项目将遗留 XML 布局迁移到 Compose实现复杂的 UI 状态管理与副作用side effects优化 Compose 性能重组次数、状态稳定性搭建带类型安全type safety的 Navigation。在仓库的分发体系中该技能同时被收录在 data/bundles.json 的core-dev与mobile-core两个 bundle 中分别对应“跨语言核心开发”与“移动端开发”两类起步组合。技能在仓库中的两种落地形态agentic-awesome-skills 对同一份技能内容提供了两条可访问路径仓库根目录的规范技能目录skills/android-jetpack-compose-expert/SKILL.md这是目录与索引引用的规范位置Claude Code 插件分发副本plugins/agentic-awesome-skills-claude/skills/android-jetpack-compose-expert/SKILL.md二者内容一致。该插件由 plugin.json 声明名为agentic-awesome-skills版本17.4.0许可证 MIT是一个“plugin-safe”的 Claude Code 分发形态。使用时你可以将其安装到 Claude Code 的插件市场或受支持的 skills 目录仓库 README 中说明了--claude等安装方式与插件流程也可以由 Agent 通过 AAS Core 的本地 MCP 在完整目录中检索并按 ID 选取该技能。技能本身只读地提供指导内容不会在目标工程中产生额外运行时依赖。第一步项目搭建与依赖版本管理技能要求libs.versions.tomlGradle 版本目录文件包含 Compose BOM 与核心库。完整继承自技能文档的原始配置如下[versions] composeBom 2024.02.01 activityCompose 1.8.2 [libraries] androidx-compose-bom { group androidx.compose, name compose-bom, version.ref composeBom } androidx-ui { group androidx.compose.ui, name ui } androidx-ui-graphics { group androidx.compose.ui, name ui-graphics } androidx-ui-tooling-preview { group androidx.compose.ui, name ui-tooling-preview } androidx-material3 { group androidx.compose.material3, name material3 } androidx-activity-compose { group androidx.activity, name activity-compose, version.ref activityCompose }配置要点BOM 统一版本compose-bom引入2024.02.01让ui、ui-graphics、ui-tooling-preview、material3等 Compose 库版本互相锁定、避免冲突——因此这些条目都不写version只写group和nameactivity-compose 单独指定版本1.8.2提供setContent { }等 Compose 与Activity的桥接能力它不属于 BOM 管理范围需独立声明material3提供 Material Design 3 组件Scaffold、CircularProgressIndicator等后文会用到的组件均来自该库。注意原文档将代码块标记为kotlin实际内容是 TOML 格式复制时应以.toml语法为准。第二步状态管理模式MVI/MVVM技能给出的核心原则用ViewModelStateFlow暴露 UI 状态绝不向 UI 层暴露MutableStateFlow。完整代码如下// UI State Definition data class UserUiState( val isLoading: Boolean false, val user: User? null, val error: String? null ) // ViewModel class UserViewModel Inject constructor( private val userRepository: UserRepository ) : ViewModel() { private val _uiState MutableStateFlow(UserUiState()) val uiState: StateFlowUserUiState _uiState.asStateFlow() fun loadUser() { viewModelScope.launch { _uiState.update { it.copy(isLoading true) } try { val user userRepository.getUser() _uiState.update { it.copy(user user, isLoading false) } } catch (e: Exception) { _uiState.update { it.copy(error e.message, isLoading false) } } } } }这段实现体现了几个可复用的工程模式单一 UI 状态对象Single Source of TruthUserUiState是data class把isLoading、user、error三个互斥维度的状态收敛到一个不可变快照里。用when分支渲染 UI 时状态组合合法且可穷举检查私有可变流 公开只读流_uiState以MutableStateFlow实现、uiState以asStateFlow()暴露。UI 层拿不到写权限只能调用loadUser()这类意图方法intention这是 MVI/MVVM 中“事件上行、状态下发”单向数据流的具体落点协程作用域绑定viewModelScope.launch { }使请求随ViewModel生命周期自动取消update { it.copy(...) }以原子 CAS 方式更新状态避免并发写丢失异常就地收敛为状态catch (e: Exception)后把e.message写入error字段并复位isLoadingUI 层因此无需处理任何回调或异常传播。第三步编写 Screen Composable 并做无状态拆分技能要求在 Screen 级 Composable 中消费状态再把纯数据向下游传递给无状态组件。完整代码Composable fun UserScreen( viewModel: UserViewModel hiltViewModel() ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() UserContent( uiState uiState, onRetry viewModel::loadUser ) } Composable fun UserContent( uiState: UserUiState, onRetry: () - Unit ) { Scaffold { padding - Box(modifier Modifier.padding(padding)) { when { uiState.isLoading - CircularProgressIndicator() uiState.error ! null - ErrorView(uiState.error, onRetry) uiState.user ! null - UserProfile(uiState.user) } } } }关键细节hiltViewModel()通过 Hilt 按屏幕作用域获取ViewModel这也是为什么UserViewModel使用Inject constructorcollectAsStateWithLifecycle()来自lifecycle-runtime-compose它在Lifecycle非STARTED状态如切到后台时自动暂停收集回到前台再恢复。相比裸collectAsState()它能避免后台无谓的重组这是 Compose 场景下推荐的收集方式UserContent完全无状态它只接收uiState数据与onRetry事件回调 lambda不含任何ViewModel依赖。这带来两个收益一是不依赖真实ViewModel即可用假数据做 Preview 与单元测试二是当onRetry引用不变时仅uiState变化触发的重组可以被 Compose 精确跳过子树Scaffold padding模式Scaffold的innerPadding用于让内容避开TopBar/BottomBar等槽位此处的when三段式加载中 / 出错 / 有数据是典型的 UI 状态渲染骨架。示例类型安全导航Navigation Compose Type Safety技能文档给出了使用 Navigation Compose 类型安全路由的完整示例// Define Destinations Serializable object Home Serializable data class Profile(val userId: String) // Setup NavHost Composable fun AppNavHost(navController: NavHostController) { NavHost(navController, startDestination Home) { composableHome { HomeScreen(onNavigateToProfile { id - navController.navigate(Profile(userId id)) }) } composableProfile { backStackEntry - val profile: Profile backStackEntry.toRoute() ProfileScreen(userId profile.userId) } } }工作方式与收益目的地即类型Home是object、Profile是携带参数的data class二者都实现Serializable基于 kotlinx.serialization。跳转navController.navigate(Profile(userId id))传递的是类型化对象而非字符串泛型 composable 注册composableHome { }以泛型形式注册框架内部序列化/反序列化路由参数拼写错误会在编译期暴露而不是在运行时抛IllegalArgumentExceptiontoRoute()还原参数目标页面通过backStackEntry.toRoute()把回退栈条目反序列化回Profile类型取出userId全程没有字符串 key 约定相比传统navController.navigate(profile/{userId}) { it.arguments ... }的字符串路由这套 API 消灭了“路由表漂移”这一类经典 Android 导航事故。最佳实践清单重组与组件设计技能文档给出两组明确规则值得作为代码评审条目应当做Do使用remember和derivedStateOf减少重组期间的不必要计算对用作 UI 状态的数据类如果其字段包含List等其他不稳定unstable类型标记为Immutable或Stable让 Compose 的 smart skip 机制能安全地跳过子树重组——因为 Compose 默认无法判断List内容未变只有作者声明“该类型不可变”后引用相等性检查才被信任使用LaunchedEffect处理由状态变化触发的一次性副作用例如弹出 Snackbar副作用被约束在 effect 生命周期内不会泄漏到重组过程中。不要做Dont不要在 Composable 函数体内直接执行昂贵操作如排序列表而不包在remember中——每次重组都会重跑该逻辑不要把ViewModel实例向下传递给子组件。子组件只接收数据state和事件回调lambda这正是第三步UserContent的写法。排障无限重组循环技能 Troubleshooting 一节给出的诊断问题出现无限重组Infinite Recomposition循环。解决方案检查以下两类典型根因——在 composition 中创建了新的对象实例例如在 Composable 体内每次重组都新建List或Modifier链而没有用remember缓存导致下游参数“看起来”每次都变了在 composition 阶段更新状态在 Composable 函数体内直接写状态而不是放在副作用LaunchedEffect、DisposableEffect或事件回调中形成“重组 → 改状态 → 触发重组”的自激环。排查工具为Layout InspectorAndroid Studio 内置可以查看每个可组合项的 recomposition count 与 skip 情况定位是哪个子树在反复重组。适用范围与限制技能 Limitations 一节明确了使用边界引用时应保持同等约束仅当任务明确符合上述范围Compose 架构、状态管理、导航、性能时才启用该技能其输出不能替代针对具体环境的验证、测试与专家评审——例如composeBom 2024.02.01是文档写定时的版本基线实际项目应结合所用 Android Gradle Plugin 与最低 API 等级核对可用版本若输入、权限、安全边界或成功标准缺失应停下来请求澄清而不是臆测补齐。小结该技能的价值在于把 Compose 生产中反复踩坑的决策固化成了可执行规范BOM 统一版本、StateFlow只读暴露、collectAsStateWithLifecycle收集、Screen/Content 两级拆分、类型安全路由、Immutable/remember驱动的重组优化以及 Layout Inspector 排障路径。结合仓库中 data/skills_index.json 与 data/bundles.json 的收录信息你可以在mobile-corebundle 中将其与android-dev、android-ui-journey-testing、expo-ui-jetpack-compose等技能组合构成一套完整的移动端 Agent 工作流。【免费下载链接】agentic-awesome-skillsAAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,115 agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.项目地址: https://gitcode.com/gh_mirrors/an/agentic-awesome-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考