Token导航 LogoToken导航

Agent Skill · 前端设计

android-architecture(安卓架构)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

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

总安装 2,376周安装 93GitHub Stars 142下载 832核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill android-architecture

这个 Skill 是做什么的

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

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。适合生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码。可整理组件结构或定位布局和性能问题,需结合项目现有设计系统使用。涉及页面改动时应配合本地预览和构建检查确认视觉效果。避免只生成孤立片段,应与路由和构建方式保持一致。

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

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

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

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

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

常见问题

6 条

android-architecture 怎么安装?

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

android-architecture 支持哪些 AI 工具?

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

android-architecture 需要什么权限?

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

android-architecture 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

android-architecture 用的人多吗?

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

android-architecture 安全吗?

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

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

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 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-architecture

安卓架构 · 本页

2,376142需要联网MIT通过

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

SKILL.md 原文

Android - Architecture

Modern Android architecture patterns following Google's recommended practices.

Key Concepts

MVVM Architecture

Model-View-ViewModel separates UI from business logic:

// UI State
data class UserUiState(
    val user: User? = null,
    val isLoading: Boolean = false,
    val error: String? = null
)

// ViewModel
class UserViewModel(
    private val userRepository: UserRepository
) : ViewModel() {

    private val _uiState = MutableStateFlow(UserUiState())
    val uiState: StateFlow<UserUiState> = _uiState.asStateFlow()

    fun loadUser(userId: String) {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true, error = null) }

            userRepository.getUser(userId)
                .onSuccess { user ->
                    _uiState.update { it.copy(user = user, isLoading = false) }
                }
                .onFailure { error ->
                    _uiState.update { it.copy(error = error.message, isLoading = false) }
                }
        }
    }
}

// Composable
@Composable
fun UserScreen(viewModel: UserViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    when {
        uiState.isLoading -> LoadingIndicator()
        uiState.error != null -> ErrorMessage(uiState.error!!)
        uiState.user != null -> UserContent(uiState.user!!)
    }
}

Clean Architecture Layers

app/
├── data/
│   ├── local/           # Room database, DataStore
│   │   ├── dao/
│   │   └── entities/
│   ├── remote/          # Retrofit, network
│   │   ├── api/
│   │   └── dto/
│   └── repository/      # Repository implementations
├── domain/
│   ├── model/           # Domain models
│   ├── repository/      # Repository interfaces
│   └── usecase/         # Business logic
└── presentation/
    ├── ui/              # Composables
    └── viewmodel/       # ViewModels

Repository Pattern

// Domain layer - interface
interface UserRepository {
    fun getUser(id: String): Flow<User>
    suspend fun saveUser(user: User): Result<Unit>
    suspend fun deleteUser(id: String): Result<Unit>
}

// Data layer - implementation
class UserRepositoryImpl(
    private val userApi: UserApi,
    private val userDao: UserDao
) : UserRepository {

    override fun getUser(id: String): Flow<User> = flow {
        // Emit cached data first
        userDao.getUser(id)?.let { emit(it.toDomain()) }

        // Fetch fresh data
        try {
            val remoteUser = userApi.getUser(id)
            userDao.insertUser(remoteUser.toEntity())
            emit(remoteUser.toDomain())
        } catch (e: Exception) {
            // Network error, cached data already emitted
        }
    }

    override suspend fun saveUser(user: User): Result<Unit> = runCatching {
        userApi.updateUser(user.toDto())
        userDao.insertUser(user.toEntity())
    }
}

Best Practices

Dependency Injection with Hilt

// Module definition
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.API_BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideUserApi(retrofit: Retrofit): UserApi {
        return retrofit.create(UserApi::class.java)
    }
}

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {

    @Binds
    @Singleton
    abstract fun bindUserRepository(impl: UserRepositoryImpl): UserRepository
}

// ViewModel injection
@HiltViewModel
class UserViewModel @Inject constructor(
    private val getUserUseCase: GetUserUseCase,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val userId: String = savedStateHandle.get<String>("userId")
        ?: throw IllegalArgumentException("userId required")

    // ViewModel implementation
}

Use Cases for Business Logic

class GetUserUseCase @Inject constructor(
    private val userRepository: UserRepository,
    private val analyticsTracker: AnalyticsTracker
) {
    operator fun invoke(userId: String): Flow<Result<User>> = flow {
        emit(Result.Loading)

        userRepository.getUser(userId)
            .catch { e ->
                analyticsTracker.trackError("get_user_failed", e)
                emit(Result.Error(e))
            }
            .collect { user ->
                emit(Result.Success(user))
            }
    }
}

// Sealed class for results
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

Room Database Setup

@Entity(tableName = "users")
data class UserEntity(
    @PrimaryKey val id: String,
    val name: String,
    val email: String,
    @ColumnInfo(name = "created_at") val createdAt: Long
)

@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :id")
    suspend fun getUser(id: String): UserEntity?

    @Query("SELECT * FROM users ORDER BY name ASC")
    fun getAllUsers(): Flow<List<UserEntity>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: UserEntity)

    @Delete
    suspend fun deleteUser(user: UserEntity)
}

@Database(entities = [UserEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

// Hilt module
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
        return Room.databaseBuilder(
            context,
            AppDatabase::class.java,
            "app_database"
        ).build()
    }

    @Provides
    fun provideUserDao(database: AppDatabase): UserDao {
        return database.userDao()
    }
}

Data Mapping

// DTO (Data Transfer Object) - from API
data class UserDto(
    @Json(name = "id") val id: String,
    @Json(name = "full_name") val fullName: String,
    @Json(name = "email_address") val email: String
)

// Entity - for Room
@Entity(tableName = "users")
data class UserEntity(
    @PrimaryKey val id: String,
    val name: String,
    val email: String
)

// Domain model
data class User(
    val id: String,
    val name: String,
    val email: String
)

// Mappers
fun UserDto.toEntity() = UserEntity(
    id = id,
    name = fullName,
    email = email
)

fun UserDto.toDomain() = User(
    id = id,
    name = fullName,
    email = email
)

fun UserEntity.toDomain() = User(
    id = id,
    name = name,
    email = email
)

fun User.toEntity() = UserEntity(
    id = id,
    name = name,
    email = email
)

Common Patterns

Single Source of Truth

class OfflineFirstRepository @Inject constructor(
    private val api: ItemApi,
    private val dao: ItemDao
) : ItemRepository {

    override fun getItems(): Flow<List<Item>> {
        return dao.getAllItems()
            .map { entities -> entities.map { it.toDomain() } }
            .onStart {
                // Refresh from network in background
                refreshItems()
            }
    }

    private suspend fun refreshItems() {
        try {
            val remoteItems = api.getItems()
            dao.deleteAll()
            dao.insertAll(remoteItems.map { it.toEntity() })
        } catch (e: Exception) {
            // Log error, local data still available
        }
    }
}

Navigation with Type-Safe Args

// Define routes
sealed class Screen(val route: String) {
    object Home : Screen("home")
    object Detail : Screen("detail/{itemId}") {
        fun createRoute(itemId: String) = "detail/$itemId"
    }
    object Settings : Screen("settings")
}

// Navigation setup
@Composable
fun AppNavigation(navController: NavHostController) {
    NavHost(navController = navController, startDestination = Screen.Home.route) {
        composable(Screen.Home.route) {
            HomeScreen(
                onItemClick = { itemId ->
                    navController.navigate(Screen.Detail.createRoute(itemId))
                }
            )
        }
        composable(
            route = Screen.Detail.route,
            arguments = listOf(navArgument("itemId") { type = NavType.StringType })
        ) { backStackEntry ->
            DetailScreen(
                itemId = backStackEntry.arguments?.getString("itemId") ?: return@composable
            )
        }
    }
}

Error Handling

sealed class UiState<out T> {
    object Loading : UiState<Nothing>()
    data class Success<T>(val data: T) : UiState<T>()
    data class Error(val message: String, val retry: (() -> Unit)? = null) : UiState<Nothing>()
}

@Composable
fun <T> StateHandler(
    state: UiState<T>,
    onRetry: () -> Unit = {},
    content: @Composable (T) -> Unit
) {
    when (state) {
        is UiState.Loading -> {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        }
        is UiState.Error -> {
            Column(
                modifier = Modifier.fillMaxSize(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                Text(state.message)
                Spacer(modifier = Modifier.height(16.dp))
                Button(onClick = onRetry) {
                    Text("Retry")
                }
            }
        }
        is UiState.Success -> content(state.data)
    }
}

Anti-Patterns

God Activity/Fragment

Bad: All logic in one Activity.

Good: Use MVVM with clear separation of concerns.

Network Calls in ViewModel

Bad:

class BadViewModel : ViewModel() {
    fun loadData() {
        val client = OkHttpClient()  // Direct network dependency
        // ...
    }
}

Good: Inject repository through constructor.

Exposing Mutable State

Bad:

class BadViewModel : ViewModel() {
    val uiState = MutableStateFlow(UiState())  // Mutable exposed!
}

Good:

class GoodViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(UiState())
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()
}

Related Skills

  • android-jetpack-compose: UI layer patterns
  • android-kotlin-coroutines: Async operations

平台分布

Claude Code

30.31%
按下载量换算252

OpenCode

21.25%
按下载量换算177

Gemini CLI

19.43%
按下载量换算162

Antigravity

11.53%
按下载量换算96

Codex

6.8%
按下载量换算57

Cursor

3.11%
按下载量换算26

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills