xiaohongshu
xiaohongshu
Expert skill for native Android development with Kotlin and Jetpack Compose
Full skill instructions
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.
bash - Execute Gradle commands, adb, and Android SDK toolsread - Analyze Kotlin source files and Gradle configurationswrite - Generate and modify Kotlin code and Compose composablesedit - Update existing Kotlin code and configurationsglob - Search for Kotlin files and Android resourcesgrep - Search for patterns in Android codebaseComposable Functions
State Management
Navigation
ViewModel Patterns
UI State Management
Coroutine Patterns
Flow Patterns
Build Configuration
KSP/KAPT
This skill integrates with the following processes:
jetpack-compose-ui.js - Compose UI developmentandroid-room-database.js - Room persistencefirebase-cloud-messaging.js - FCM integrationandroid-playstore-publishing.js - Play Store submissionapp/
├── 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
# gradle/libs.versions.toml
[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 = "com.android.application", version = "8.2.0" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
ksp = { id = "com.google.devtools.ksp", version = "1.9.21-1.0.16" }
// ui/feature/home/HomeScreen.kt
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)
)
}
}
}
}
@Composable
private fun ItemCard(
item: Item,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Card(
onClick = onClick,
modifier = modifier.fillMaxWidth()
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = item.title,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = item.description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
// ui/feature/home/HomeViewModel.kt
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 Error(val message: String) : HomeUiState
}
// ui/navigation/NavGraph.kt
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() }
)
}
}
}
// di/AppModule.kt
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::class.java,
"app_database"
).build()
}
@Provides
fun provideItemDao(database: AppDatabase) = database.itemDao()
}
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
# Clean build
./gradlew clean
# Build debug APK
./gradlew assembleDebug
# Build release AAB
./gradlew bundleRelease
# Run unit tests
./gradlew testDebugUnitTest
# Run instrumented tests
./gradlew connectedDebugAndroidTest
# Run lint
./gradlew lintDebug
# Install on device
./gradlew installDebug
Gradle sync failures
./gradlew --refresh-dependencies
KSP/KAPT issues
./gradlew clean && ./gradlew kspDebugKotlin
Emulator issues
adb kill-server && adb start-server
Compose preview issues
# Invalidate caches: File > Invalidate Caches / Restart
android-room - Room database integrationfirebase-mobile - Firebase servicesmobile-testing - Comprehensive testinggoogle-play-console - Play Store publishingxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience