android-development

安装量: 36
排名: #19443

安装

npx skills add https://github.com/dpconde/claude-android-skill --skill android-development

Android Development

Build Android applications following Google's official architecture guidance, as demonstrated in the NowInAndroid reference app.

Quick Reference Task Reference File Project structure & modules modularization.md Architecture layers (UI, Domain, Data) architecture.md Jetpack Compose patterns compose-patterns.md Gradle & build configuration gradle-setup.md Testing approach testing.md Workflow Decision Tree

Creating a new project? → Read modularization.md for project structure → Use templates in assets/templates/

Adding a new feature? → Create feature module with api and impl submodules → Follow patterns in architecture.md

Building UI screens? → Read compose-patterns.md → Create Screen + ViewModel + UiState

Setting up data layer? → Read data layer section in architecture.md → Create Repository + DataSource + DAO

Core Principles Offline-first: Local database is source of truth, sync with remote Unidirectional data flow: Events flow down, data flows up Reactive streams: Use Kotlin Flow for all data exposure Modular by feature: Each feature is self-contained with clear boundaries Testable by design: Use interfaces and test doubles, no mocking libraries Architecture Layers ┌─────────────────────────────────────────┐ │ UI Layer │ │ (Compose Screens + ViewModels) │ ├─────────────────────────────────────────┤ │ Domain Layer │ │ (Use Cases - optional, for reuse) │ ├─────────────────────────────────────────┤ │ Data Layer │ │ (Repositories + DataSources) │ └─────────────────────────────────────────┘

Module Types app/ # App module - navigation, scaffolding feature/ ├── featurename/ │ ├── api/ # Navigation keys (public) │ └── impl/ # Screen, ViewModel, DI (internal) core/ ├── data/ # Repositories ├── database/ # Room DAOs, entities ├── network/ # Retrofit, API models ├── model/ # Domain models (pure Kotlin) ├── common/ # Shared utilities ├── ui/ # Reusable Compose components ├── designsystem/ # Theme, icons, base components ├── datastore/ # Preferences storage └── testing/ # Test utilities

Creating a New Feature Create feature:myfeature:api module with navigation key Create feature:myfeature:impl module with: MyFeatureScreen.kt - Composable UI MyFeatureViewModel.kt - State holder MyFeatureUiState.kt - Sealed interface for states MyFeatureNavigation.kt - Navigation setup MyFeatureModule.kt - Hilt DI module Standard File Patterns ViewModel Pattern @HiltViewModel class MyFeatureViewModel @Inject constructor( private val myRepository: MyRepository, ) : ViewModel() {

val uiState: StateFlow<MyFeatureUiState> = myRepository
    .getData()
    .map { data -> MyFeatureUiState.Success(data) }
    .stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5_000),
        initialValue = MyFeatureUiState.Loading,
    )

fun onAction(action: MyFeatureAction) {
    when (action) {
        is MyFeatureAction.ItemClicked -> handleItemClick(action.id)
    }
}

}

UiState Pattern sealed interface MyFeatureUiState { data object Loading : MyFeatureUiState data class Success(val items: List) : MyFeatureUiState data class Error(val message: String) : MyFeatureUiState }

Screen Pattern @Composable internal fun MyFeatureRoute( onNavigateToDetail: (String) -> Unit, viewModel: MyFeatureViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() MyFeatureScreen( uiState = uiState, onAction = viewModel::onAction, onNavigateToDetail = onNavigateToDetail, ) }

@Composable internal fun MyFeatureScreen( uiState: MyFeatureUiState, onAction: (MyFeatureAction) -> Unit, onNavigateToDetail: (String) -> Unit, ) { when (uiState) { is MyFeatureUiState.Loading -> LoadingIndicator() is MyFeatureUiState.Success -> ContentList(uiState.items, onAction) is MyFeatureUiState.Error -> ErrorMessage(uiState.message) } }

Repository Pattern interface MyRepository { fun getData(): Flow> suspend fun updateItem(id: String, data: MyModel) }

internal class OfflineFirstMyRepository @Inject constructor( private val localDataSource: MyDao, private val networkDataSource: MyNetworkApi, ) : MyRepository {

override fun getData(): Flow<List<MyModel>> =
    localDataSource.getAll().map { entities ->
        entities.map { it.toModel() }
    }

override suspend fun updateItem(id: String, data: MyModel) {
    localDataSource.upsert(data.toEntity())
}

}

Key Dependencies // Gradle version catalog (libs.versions.toml) [versions] kotlin = "1.9.x" compose-bom = "2024.x.x" hilt = "2.48" room = "2.6.x" coroutines = "1.7.x"

[libraries] androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }

Build Configuration

Use convention plugins in build-logic/ for consistent configuration:

AndroidApplicationConventionPlugin - App modules AndroidLibraryConventionPlugin - Library modules AndroidFeatureConventionPlugin - Feature modules AndroidComposeConventionPlugin - Compose setup AndroidHiltConventionPlugin - Hilt setup

See gradle-setup.md for complete build configuration.

返回排行榜