[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-a6581d59-3ac5-4e02-955c-4dba5bf0b486":3,"$fVpJmhs1GiLA261blIDNa1k1C1rvTgE99WOaBPjl_OR0":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"a6581d59-3ac5-4e02-955c-4dba5bf0b486","android-jetpack-compose-expert","使用Jetpack Compose构建现代Android UI的专业指导，涵盖状态管理、导航、性能和Material Design 3。","cat_coding_frontend","mod_coding","sickn33,coding","---\nname: android-jetpack-compose-expert\ndescription: \"Expert guidance for building modern Android UIs with Jetpack Compose, covering state management, navigation, performance, and Material Design 3.\"\nrisk: safe\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# Android Jetpack Compose Expert\n\n## Overview\n\nA comprehensive guide for building production-quality Android applications using Jetpack Compose. This skill covers architectural patterns, state management with ViewModels, navigation type-safety, and performance optimization techniques.\n\n## When to Use This Skill\n\n- Use when starting a new Android project with Jetpack Compose.\n- Use when migrating legacy XML layouts to Compose.\n- Use when implementing complex UI state management and side effects.\n- Use when optimizing Compose performance (recomposition counts, stability).\n- Use when setting up Navigation with type safety.\n\n## Step-by-Step Guide\n\n### 1. Project Setup & Dependencies\n\nEnsure your `libs.versions.toml` includes the necessary Compose BOM and libraries.\n\n```kotlin\n[versions]\ncomposeBom = \"2024.02.01\"\nactivityCompose = \"1.8.2\"\n\n[libraries]\nandroidx-compose-bom = { group = \"androidx.compose\", name = \"compose-bom\", version.ref = \"composeBom\" }\nandroidx-ui = { group = \"androidx.compose.ui\", name = \"ui\" }\nandroidx-ui-graphics = { group = \"androidx.compose.ui\", name = \"ui-graphics\" }\nandroidx-ui-tooling-preview = { group = \"androidx.compose.ui\", name = \"ui-tooling-preview\" }\nandroidx-material3 = { group = \"androidx.compose.material3\", name = \"material3\" }\nandroidx-activity-compose = { group = \"androidx.activity\", name = \"activity-compose\", version.ref = \"activityCompose\" }\n```\n\n### 2. State Management Pattern (MVI\u002FMVVM)\n\nUse `ViewModel` with `StateFlow` to expose UI state. Avoid exposing `MutableStateFlow`.\n\n```kotlin\n\u002F\u002F UI State Definition\ndata class UserUiState(\n    val isLoading: Boolean = false,\n    val user: User? = null,\n    val error: String? = null\n)\n\n\u002F\u002F ViewModel\nclass UserViewModel @Inject constructor(\n    private val userRepository: UserRepository\n) : ViewModel() {\n\n    private val _uiState = MutableStateFlow(UserUiState())\n    val uiState: StateFlow\u003CUserUiState> = _uiState.asStateFlow()\n\n    fun loadUser() {\n        viewModelScope.launch {\n            _uiState.update { it.copy(isLoading = true) }\n            try {\n                val user = userRepository.getUser()\n                _uiState.update { it.copy(user = user, isLoading = false) }\n            } catch (e: Exception) {\n                _uiState.update { it.copy(error = e.message, isLoading = false) }\n            }\n        }\n    }\n}\n```\n\n### 3. Creating the Screen Composable\n\nConsume the state in a \"Screen\" composable and pass data down to stateless components.\n\n```kotlin\n@Composable\nfun UserScreen(\n    viewModel: UserViewModel = hiltViewModel()\n) {\n    val uiState by viewModel.uiState.collectAsStateWithLifecycle()\n\n    UserContent(\n        uiState = uiState,\n        onRetry = viewModel::loadUser\n    )\n}\n\n@Composable\nfun UserContent(\n    uiState: UserUiState,\n    onRetry: () -> Unit\n) {\n    Scaffold { padding ->\n        Box(modifier = Modifier.padding(padding)) {\n            when {\n                uiState.isLoading -> CircularProgressIndicator()\n                uiState.error != null -> ErrorView(uiState.error, onRetry)\n                uiState.user != null -> UserProfile(uiState.user)\n            }\n        }\n    }\n}\n```\n\n## Examples\n\n### Example 1: Type-Safe Navigation\n\nUsing the new Navigation Compose Type Safety (available in recent versions).\n\n```kotlin\n\u002F\u002F Define Destinations\n@Serializable\nobject Home\n\n@Serializable\ndata class Profile(val userId: String)\n\n\u002F\u002F Setup NavHost\n@Composable\nfun AppNavHost(navController: NavHostController) {\n    NavHost(navController, startDestination = Home) {\n        composable\u003CHome> {\n            HomeScreen(onNavigateToProfile = { id ->\n                navController.navigate(Profile(userId = id))\n            })\n        }\n        composable\u003CProfile> { backStackEntry ->\n            val profile: Profile = backStackEntry.toRoute()\n            ProfileScreen(userId = profile.userId)\n        }\n    }\n}\n```\n\n## Best Practices\n\n- ✅ **Do:** Use `remember` and `derivedStateOf` to minimize unnecessary calculations during recomposition.\n- ✅ **Do:** Mark data classes used in UI state as `@Immutable` or `@Stable` if they contain `List` or other unstable types to enable smart recomposition skipping.\n- ✅ **Do:** Use `LaunchedEffect` for one-off side effects (like showing a Snackbar) triggered by state changes.\n- ❌ **Don't:** Perform expensive operations (like sorting a list) directly inside the Composable function body without `remember`.\n- ❌ **Don't:** Pass `ViewModel` instances down to child components. Pass only the data (state) and lambda callbacks (events).\n\n## Troubleshooting\n\n**Problem:** Infinite Recomposition loop.\n**Solution:** Check if you are creating new object instances (like `List` or `Modifier`) inside the composition without `remember`, or if you are updating state inside the composition phase instead of a side-effect or callback. Use Layout Inspector to debug recomposition counts.\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,209,2077,"2026-05-16 13:02:47",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"前端开发","frontend","mdi-language-html5","HTML\u002FCSS\u002FJavaScript\u002F框架相关",1,96,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"1033d811-ba64-4dbe-98b4-fe63e00e791a","1.0.0","android-jetpack-compose-expert.zip",2328,"uploads\u002Fskills\u002Fa6581d59-3ac5-4e02-955c-4dba5bf0b486\u002Fandroid-jetpack-compose-expert.zip","40f884105793948ff743bfe6db9926b1c1590e5826b0461d81336a74f087ffbb","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":5460}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]