| name | Kotlin/Jetpack Compose Development |
| description | Expert skill for native Android development with Kotlin and Jetpack Compose |
| version | 1.0.0 |
| category | Native Android Development |
| slug | kotlin-compose |
| status | active |
| graph | {"domains":["domain:mobile"],"specializations":["specialization:mobile-development"],"skillAreas":["skill-area:android-native","skill-area:mobile-state-management"],"roles":["role:mobile-engineer"],"workflows":["workflow:feature-development","workflow:release-management"],"topics":["topic:accessibility"]} |
Kotlin/Jetpack Compose Development Skill
Overview
This skill provides expert capabilities for native Android development using Kotlin and Jetpack Compose. It enables generation of Compose UI components, implementation of modern Android architecture patterns, and comprehensive Gradle build operations.
Allowed Tools
bash - Execute Gradle commands, adb, and Android SDK tools
read - Analyze Kotlin source files and Gradle configurations
write - Generate and modify Kotlin code and Compose composables
edit - Update existing Kotlin code and configurations
glob - Search for Kotlin files and Android resources
grep - Search for patterns in Android codebase
Capabilities
Jetpack Compose
-
Composable Functions
- Create Material Design 3 composables
- Implement custom layouts with Layout composable
- Build reusable UI components
- Generate preview annotations
- Create multi-preview configurations
-
State Management
- Implement remember and rememberSaveable
- Use state hoisting patterns
- Configure derivedStateOf for computed state
- Implement snapshotFlow for side effects
- Handle configuration changes
-
Navigation
- Configure Compose Navigation with NavHost
- Implement type-safe navigation with arguments
- Set up nested navigation graphs
- Handle deep links with NavDeepLink
- Implement bottom navigation with BottomNavigation
ViewModel Integration
-
ViewModel Patterns
- Create ViewModels with Hilt injection
- Implement StateFlow and SharedFlow
- Configure SavedStateHandle
- Handle process death recovery
- Use viewModelScope for coroutines
-
UI State Management
- Design sealed class UI states
- Implement loading, error, and success states
- Configure pull-to-refresh
- Handle pagination with Paging 3
- Implement search with debouncing
Kotlin Coroutines
-
Coroutine Patterns
- Configure CoroutineScope and dispatchers
- Implement structured concurrency
- Handle cancellation properly
- Use SupervisorJob for error isolation
- Configure ExceptionHandler
-
Flow Patterns
- Create cold and hot Flows
- Implement StateFlow and SharedFlow
- Configure Flow operators
- Handle backpressure with buffer
- Transform Flows with map, filter, combine
Dependency Injection
- Hilt Integration
- Configure Hilt modules
- Implement @Inject annotations
- Set up ViewModelComponent
- Configure Singleton and Scoped bindings
- Use @EntryPoint for framework classes
Gradle Build System
-
Build Configuration
- Configure build.gradle.kts with Kotlin DSL
- Set up build variants and flavors
- Configure ProGuard/R8 rules
- Implement version catalogs
- Set up composite builds
-
KSP/KAPT
- Configure Kotlin Symbol Processing
- Set up Room with KSP
- Configure Hilt with KAPT
- Generate code with custom processors
Testing
- Testing Frameworks
- Write JUnit 5 unit tests
- Implement Compose UI tests
- Configure test rules and fixtures
- Mock dependencies with MockK
- Set up Robolectric for JVM tests
Target Processes
This skill integrates with the following processes:
jetpack-compose-ui.js - Compose UI development
android-room-database.js - Room persistence
firebase-cloud-messaging.js - FCM integration
android-playstore-publishing.js - Play Store submission
Dependencies
Required
- Android Studio Hedgehog or later
- Android SDK 34+
- Kotlin 1.9+
- Gradle 8.2+
Optional
- Android Emulator
- Firebase tools
- adb (Android Debug Bridge)
- Layout Inspector
Configuration
Project Structure
app/
├── src/
│ ├── main/
│ │ ├── kotlin/com/example/myapp/
│ │ │ ├── MyApplication.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── di/
│ │ │ │ └── AppModule.kt
│ │ │ ├── data/
│ │ │ │ ├── repository/
│ │ │ │ ├── local/
│ │ │ │ └── remote/
│ │ │ ├── domain/
│ │ │ │ ├── model/
│ │ │ │ ├── repository/
│ │ │ │ └── usecase/
│ │ │ └── ui/
│ │ │ ├── theme/
│ │ │ ├── navigation/
│ │ │ └── feature/
│ │ ├── res/
│ │ └── AndroidManifest.xml
│ ├── test/
│ └── androidTest/
├── build.gradle.kts
└── proguard-rules.pro
Version Catalog
[versions]
kotlin = "1.9.21"
compose-bom = "2024.01.00"
hilt = "2.50"
room = "2.6.1"
lifecycle = "2.7.0"
[libraries]
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "ui" }
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
compose-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[plugins]
android-application = { id = , version = }
= { id = , version.ref = }
= { id = , version.ref = }
= { id = , version = }
Usage Examples
Create Composable Screen
package com.example.myapp.ui.feature.home
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(
viewModel: HomeViewModel = hiltViewModel(),
onItemClick: (String) -> Unit
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
Scaffold(
topBar = {
TopAppBar(
title = { Text("Home") }
)
}
) { paddingValues ->
when (val state = uiState) {
is HomeUiState.Loading -> {
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
is HomeUiState.Success -> {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(state.items, key = { it.id }) { item ->
ItemCard(
item = item,
onClick = { onItemClick(item.id) }
)
}
}
}
is HomeUiState.Error -> {
ErrorContent(
message = state.message,
onRetry = viewModel::retry,
modifier = Modifier.padding(paddingValues)
)
}
}
}
}
{
Card(
onClick = onClick,
modifier = modifier.fillMaxWidth()
) {
Column(
modifier = Modifier.padding(dp)
) {
Text(
text = item.title,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(dp))
Text(
text = item.description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
Implement ViewModel
package com.example.myapp.ui.feature.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor(
private val getItemsUseCase: GetItemsUseCase
) : ViewModel() {
private val _uiState = MutableStateFlow<HomeUiState>(HomeUiState.Loading)
val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()
init {
loadItems()
}
private fun loadItems() {
viewModelScope.launch {
_uiState.value = HomeUiState.Loading
getItemsUseCase()
.catch { e ->
_uiState.value = HomeUiState.Error(e.message ?: "Unknown error")
}
.collect { items ->
_uiState.value = HomeUiState.Success(items)
}
}
}
fun retry() {
loadItems()
}
}
sealed interface HomeUiState {
data object Loading : HomeUiState
data class Success(val items: List<Item>) : HomeUiState
data class ( message: String) : HomeUiState
}
Configure Navigation
package com.example.myapp.ui.navigation
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import com.example.myapp.ui.feature.home.HomeScreen
import com.example.myapp.ui.feature.detail.DetailScreen
sealed class Screen(val route: String) {
data object Home : Screen("home")
data object Detail : Screen("detail/{itemId}") {
fun createRoute(itemId: String) = "detail/$itemId"
}
}
@Composable
fun NavGraph(
navController: NavHostController,
startDestination: String = Screen.Home.route
) {
NavHost(
navController = navController,
startDestination = startDestination
) {
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 ->
val itemId = backStackEntry.arguments?.getString("itemId") ?: return@composable
DetailScreen(
itemId = itemId,
onBackClick = { navController.popBackStack() }
)
}
}
}
Configure Hilt Module
package com.example.myapp.di
import android.content.Context
import androidx.room.Room
import com.example.myapp.data.local.AppDatabase
import com.example.myapp.data.remote.ApiService
import com.example.myapp.data.repository.ItemRepositoryImpl
import com.example.myapp.domain.repository.ItemRepository
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindItemRepository(impl: ItemRepositoryImpl): ItemRepository
}
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(
context,
AppDatabase::.java,
).build()
}
= database.itemDao()
}
NetworkModule {
: Retrofit {
Retrofit.Builder()
.baseUrl()
.addConverterFactory(MoshiConverterFactory.create())
.build()
}
: ApiService {
retrofit.create(ApiService::.java)
}
}
Build Commands
./gradlew clean
./gradlew assembleDebug
./gradlew bundleRelease
./gradlew testDebugUnitTest
./gradlew connectedDebugAndroidTest
./gradlew lintDebug
./gradlew installDebug
Quality Gates
Code Quality
- Kotlin compiler warnings treated as errors
- Detekt/ktlint compliance
- No deprecated API usage
- Proper coroutine scope management
Performance Benchmarks
- App startup < 500ms (cold start)
- 60fps during scrolling and animations
- No memory leaks (LeakCanary verification)
- Minimized recompositions
Test Coverage
- Unit test coverage > 80%
- UI test coverage for critical flows
- Screenshot tests for UI components
Error Handling
Common Issues
-
Gradle sync failures
./gradlew --refresh-dependencies
-
KSP/KAPT issues
./gradlew clean && ./gradlew kspDebugKotlin
-
Emulator issues
adb kill-server && adb start-server
-
Compose preview issues
Related Skills
android-room - Room database integration
firebase-mobile - Firebase services
mobile-testing - Comprehensive testing
google-play-console - Play Store publishing
Version History
- 1.0.0 - Initial release with core Kotlin/Compose capabilities