Token导航 LogoToken导航

Agent Skill · 前端设计

android-compose(安卓撰写)

android-compose 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

android-compose 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 9,393。

总安装 218周安装 9GitHub Stars 8下载 71核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:android-compose(安卓撰写)
来源仓库:https://github.com/ar4mirez/samuel
仓库路径:skills/android-compose
安装命令:
npx skills add https://github.com/ar4mirez/samuel --skill android-compose
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/ar4mirez/samuel --skill android-compose

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于 Jetpack Compose 声明式 UI 开发的完整指南与规范参考。涵盖单向数据流、状态提升、生命周期感知与 Material Design 3 适配。提供可组合函数编写规范与性能优化 guardrails 清单。适用于构建响应式、可维护且高性能的 Android 用户界面。

安装前请确保项目满足最低 SDK 与 Kotlin 版本要求。

来源仓库内路径:skills/android-compose

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/ar4mirez/samuel --skill android-compose;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

android-compose 怎么安装?

在终端执行 npx skills add https://github.com/ar4mirez/samuel --skill android-compose。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

android-compose 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

android-compose 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

android-compose 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

android-compose 用的人多吗?

公开数据是累计安装 218 次,近一周安装 9 次,下载 71 次,GitHub 8 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

android-compose 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
android-compose

安卓撰写 · 本页

2188需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Android Jetpack Compose Guide

Applies to: Android SDK 24+, Jetpack Compose 1.5+, Kotlin 1.9+, Material Design 3

Core Principles

  1. Declarative UI: Describe what the UI should look like, not how to build it step-by-step
  2. Unidirectional Data Flow: State flows down, events flow up -- always
  3. Composable Functions Are Cheap: The framework handles when to recompose; keep composables pure
  4. State Hoisting: Lift state to the nearest common ancestor that needs it
  5. Lifecycle Awareness: Collect flows with collectAsStateWithLifecycle(), never raw collectAsState()

Guardrails

Composable Conventions

  • Every composable accepts modifier: Modifier = Modifier as its first optional parameter
  • Keep composables small and focused (one responsibility per function)
  • Use @Preview on every reusable component with representative data
  • Never perform side effects (network, DB, analytics) directly inside a composable body
  • Use LaunchedEffect, DisposableEffect, or SideEffect for side-effect work
  • Prefer stateless composables; hoist state to the caller or ViewModel
// BAD: side effects in composition
@Composable
fun UserList(users: List<User>) {
    analytics.trackScreenView("user_list") // fires on every recomposition
    LazyColumn { ... }
}

// GOOD: side effect in LaunchedEffect
@Composable
fun UserList(users: List<User>) {
    LaunchedEffect(Unit) {
        analytics.trackScreenView("user_list")
    }
    LazyColumn { ... }
}

State Management

  • Use StateFlow in ViewModel, collect with collectAsStateWithLifecycle()
  • Model UI state as a sealed interface (Loading, Success, Error)
  • Never expose MutableStateFlow publicly from a ViewModel
  • Use remember for local composable state; rememberSaveable when it must survive config changes
  • Use derivedStateOf for expensive computations that depend on other state
// Sealed UI state pattern
sealed interface HomeUiState {
    data object Loading : HomeUiState
    data class Success(val users: List<User>) : HomeUiState
    data class Error(val message: String) : HomeUiState
}

// ViewModel exposes immutable StateFlow
@HiltViewModel
class HomeViewModel @Inject constructor(
    private val userRepository: UserRepository,
) : ViewModel() {
    private val _uiState = MutableStateFlow<HomeUiState>(HomeUiState.Loading)
    val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()

    fun loadUsers() {
        viewModelScope.launch {
            _uiState.value = HomeUiState.Loading
            userRepository.getUsers()
                .catch { e -> _uiState.value = HomeUiState.Error(e.message ?: "Unknown error") }
                .collect { users -> _uiState.value = HomeUiState.Success(users) }
        }
    }
}

// Screen collects lifecycle-aware
@Composable
fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    when (val state = uiState) {
        is HomeUiState.Loading -> LoadingIndicator()
        is HomeUiState.Success -> UserList(state.users)
        is HomeUiState.Error -> ErrorMessage(state.message, onRetry = viewModel::loadUsers)
    }
}

Navigation

  • Define routes as a sealed class or sealed interface for type safety
  • Never pass complex objects as navigation arguments; pass IDs and load from ViewModel
  • Clear back stack correctly with popUpTo and inclusive when navigating to auth screens
  • Use hiltViewModel() inside composable {} blocks for scoped ViewModels
sealed class Screen(val route: String) {
    data object Login : Screen("login")
    data object Home : Screen("home")
    data object Detail : Screen("detail/{userId}") {
        fun createRoute(userId: String) = "detail/$userId"
    }
}

@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = Screen.Home.route) {
        composable(Screen.Home.route) {
            HomeScreen(onUserClick = { userId ->
                navController.navigate(Screen.Detail.createRoute(userId))
            })
        }
        composable(
            route = Screen.Detail.route,
            arguments = listOf(navArgument("userId") { type = NavType.StringType }),
        ) { backStackEntry ->
            val userId = backStackEntry.arguments?.getString("userId") ?: ""
            DetailScreen(userId = userId, onBack = { navController.popBackStack() })
        }
    }
}

Material 3 Theming

  • Always wrap the app root in your custom MaterialTheme composable
  • Support dynamic color on Android 12+ with dynamicLightColorScheme / dynamicDarkColorScheme
  • Define color tokens in a dedicated Color.kt; typography in Type.kt; theme in Theme.kt
  • Use MaterialTheme.colorScheme.* and MaterialTheme.typography.* instead of hardcoded values
  • Support both light and dark themes from day one
@Composable
fun MyAppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit,
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }
        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    MaterialTheme(colorScheme = colorScheme, typography = Typography, content = content)
}

Dependency Injection (Hilt)

  • Annotate Application with @HiltAndroidApp, Activity with @AndroidEntryPoint
  • Annotate ViewModels with @HiltViewModel and use @Inject constructor
  • Use hiltViewModel() in composables, never construct ViewModels manually
  • Organize DI modules by layer: AppModule, NetworkModule, DatabaseModule

Lifecycle & Effects

EffectTriggerUse for
LaunchedEffect(key)On enter + when key changesOne-shot loads, navigation events
DisposableEffect(key)On enter + when key changes (with cleanup)Listeners, observers, callbacks
SideEffectAfter every successful recompositionSyncing compose state to non-compose
rememberCoroutineScope()Manual launch from callbacksButton clicks launching coroutines
// One-shot load on screen enter
LaunchedEffect(Unit) { viewModel.loadData() }

// Clean up a listener when leaving composition
DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event -> ... }
    lifecycleOwner.lifecycle.addObserver(observer)
    onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}

Project Structure

app/src/main/java/com/example/myapp/
├── MyApplication.kt               # @HiltAndroidApp
├── MainActivity.kt                # @AndroidEntryPoint, setContent {}
├── navigation/
│   └── AppNavigation.kt           # NavHost, route definitions
├── ui/
│   ├── theme/                     # Color.kt, Type.kt, Theme.kt
│   ├── screens/                   # Feature screens
│   │   ├── home/
│   │   │   ├── HomeScreen.kt      # Composable
│   │   │   └── HomeViewModel.kt   # ViewModel + UiState
│   │   └── detail/
│   │       ├── DetailScreen.kt
│   │       └── DetailViewModel.kt
│   └── components/                # Shared composables
│       ├── LoadingIndicator.kt
│       └── ErrorMessage.kt
├── data/
│   ├── model/                     # Domain models (@Serializable)
│   ├── remote/                    # Retrofit service, DTOs
│   ├── local/                     # Room database, DAOs
│   └── repository/                # Repository implementations
└── di/                            # Hilt modules
    ├── AppModule.kt
    └── NetworkModule.kt
  • ui/screens/: One sub-package per feature, each with Screen.kt + ViewModel.kt
  • ui/components/: Reusable composables shared across screens
  • data/: Models, repositories, API services; no Compose dependencies here
  • di/: Hilt modules providing singletons and scoped dependencies

Key Dependencies

// build.gradle.kts (app)
val composeBom = platform("androidx.compose:compose-bom:2024.01.00")
implementation(composeBom)
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.activity:activity-compose:1.8.2")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
implementation("androidx.navigation:navigation-compose:2.7.6")
implementation("androidx.hilt:hilt-navigation-compose:1.1.0")
implementation("com.google.dagger:hilt-android:2.50")
ksp("com.google.dagger:hilt-compiler:2.50")
implementation("io.coil-kt:coil-compose:2.5.0")

// Testing
testImplementation("junit:junit:4.13.2")
testImplementation("io.mockk:mockk:1.13.9")
testImplementation("app.cash.turbine:turbine:1.0.0")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
androidTestImplementation(composeBom)
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")

Testing

ViewModel Unit Tests

  • Use StandardTestDispatcher + Dispatchers.setMain() for coroutine control
  • Use Turbine for StateFlow assertions
  • Use MockK with coEvery / coVerify for suspend function mocking
  • Reset dispatcher in @After with Dispatchers.resetMain()
@OptIn(ExperimentalCoroutinesApi::class)
class HomeViewModelTest {
    private val testDispatcher = StandardTestDispatcher()
    private val userRepository = mockk<UserRepository>()

    @Before fun setup() { Dispatchers.setMain(testDispatcher) }
    @After fun tearDown() { Dispatchers.resetMain() }

    @Test
    fun `loadUsers emits Success state on valid data`() = runTest {
        val users = listOf(User(id = "1", email = "a@b.com", name = "Alice"))
        coEvery { userRepository.getUsers() } returns flowOf(users)

        val viewModel = HomeViewModel(userRepository)
        advanceUntilIdle()

        viewModel.uiState.test {
            val state = awaitItem()
            assertTrue(state is HomeUiState.Success)
            assertEquals(users, (state as HomeUiState.Success).users)
        }
    }
}

Compose UI Tests

  • Use createComposeRule() for isolated composable tests
  • Query nodes with onNodeWithText, onNodeWithTag, onNodeWithContentDescription
  • Assert with assertExists(), assertIsDisplayed(), assertIsEnabled()
  • Perform actions with performClick(), performTextInput()
class HomeScreenTest {
    @get:Rule val composeTestRule = createComposeRule()

    @Test
    fun displays_user_name_when_loaded() {
        composeTestRule.setContent {
            MyAppTheme {
                UserCard(user = User("1", "a@b.com", "Alice"), onClick = {}, onDeleteClick = {})
            }
        }
        composeTestRule.onNodeWithText("Alice").assertIsDisplayed()
        composeTestRule.onNodeWithText("a@b.com").assertIsDisplayed()
    }
}

Commands

# Build
./gradlew assembleDebug            # Debug APK
./gradlew assembleRelease          # Release APK
./gradlew bundleRelease            # AAB for Play Store

# Test
./gradlew test                     # Unit tests
./gradlew connectedAndroidTest     # Instrumented tests on device/emulator

# Quality
./gradlew lint                     # Android Lint
./gradlew ktlintCheck              # Code style check
./gradlew ktlintFormat             # Auto-fix formatting
./gradlew detekt                   # Static analysis

# Install & Run
./gradlew installDebug             # Install on connected device
./gradlew clean                    # Clean build artifacts

Best Practices Summary

Do

  • Use collectAsStateWithLifecycle() for all Flow collection in composables
  • Use remember {} for expensive local computations
  • Use LaunchedEffect for one-shot side effects, DisposableEffect for cleanup
  • Keep composables stateless; hoist state to ViewModel or caller
  • Use sealed interfaces for UI state with exhaustive when expressions
  • Provide contentDescription on all interactive and decorative icons
  • Use Modifier chaining; accept modifier parameter in every public composable
  • Preview every reusable component with @Preview

Avoid

  • Performing I/O, network calls, or analytics tracking directly in composable bodies
  • Exposing MutableStateFlow or MutableState from ViewModels
  • Using !! operator in production code
  • Hardcoding colors, dimensions, or strings (use theme tokens and resources)
  • Creating ViewModels manually (use hiltViewModel())
  • Passing complex objects through navigation arguments (pass IDs instead)
  • Ignoring configuration changes (use rememberSaveable when needed)

References

For detailed UI patterns, animation, testing strategies, performance, and accessibility guidance, see:

External References

平台分布

Codex

37.41%
按下载量换算27

Claude

31.3%
按下载量换算22

Cursor

16.72%
按下载量换算12

Gemini CLI

9.02%
按下载量换算6

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills