Skip to main content

android-native-dev

Android native application development and UI design guide. Covers Material Design 3, Kotlin/Compose development, project configuration, accessibility, and build troubleshooting. Read this before Android native application development.

来源信息

仓库
MiniMax-AI/skills
最近来源活动
2026年3月25日 15:48
检测到的 SKILL.md 语言
英语
星标
13,714
分支
1,199

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
10 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
android-native-dev
description
Android native application development and UI design guide. Covers Material Design 3, Kotlin/Compose development, project configuration, accessibility, and build troubleshooting. Read this before Android native application development.
license
MIT
metadata
{"version":"1.0.0","category":"mobile","sources":["Material Design 3 Guidelines (material.io)","Android Developer Documentation (developer.android.com)","Google Play Quality Guidelines","WCAG Accessibility Guidelines"]}
## 1. Project Scenario Assessment Before starting development, assess the current project state: | Scenario | Characteristics | Approach | |----------|-----------------|----------| | **Empty Directory** | No files present | Full initialization required, including Gradle Wrapper | | **Has Gradle Wrapper** | `gradlew` and `gradle/wrapper/` exist | Use `./gradlew` directly for builds | | **Android Studio Project** | Complete project structure, may lack wrapper | Check wrapper, run `gradle wrapper` if needed | | **Incomplete Project** | Partial files present | Check missing files, complete configuration | **Key Principles**: - Before writing business logic, ensure `./gradlew assembleDebug` succeeds - If `gradle.properties` is missing, create it first and configure AndroidX ### 1.1 Required Files Checklist ``` MyApp/ ├── gradle.properties # Configure AndroidX and other settings ├── settings.gradle.kts ├── build.gradle.kts # Root level ├── gradle/wrapper/ │ └── gradle-wrapper.properties ├── app/ │ ├── build.gradle.kts # Module level │ └── src/main/ │ ├── AndroidManifest.xml │ ├── java/com/example/myapp/ │ │ └── MainActivity.kt │ └── res/ │ ├── values/ │ │ ├── strings.xml │ │ ├── colors.xml │ │ └── themes.xml │ └── mipmap-*/ # App icons ``` --- ## 2. Project Configuration ### 2.1 gradle.properties ```properties # Required configuration android.useAndroidX=true android.enableJetifier=true # Build optimization org.gradle.parallel=true kotlin.code.style=official # JVM memory settings (adjust based on project size) # Small projects: 2048m, Medium: 4096m, Large: 8192m+ # org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 ``` > **Note**: If you encounter `OutOfMemoryError` during build, increase `-Xmx` value. Large projects with many dependencies may require 8GB or more. ### 2.2 Dependency Declaration Standards ```kotlin dependencies { // Use BOM to manage Compose versions implementation(platform("androidx.compose:compose-bom:2024.02.00")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.material3:material3") // Activity & ViewModel implementation("androidx.activity:activity-compose:1.8.2") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") } ``` ### 2.3 Build Variants & Product Flavors Product Flavors allow you to create different versions of your app (e.g., free/paid, dev/staging/prod). **Configuration in app/build.gradle.kts**: ```kotlin android { // Define flavor dimensions flavorDimensions += "environment" productFlavors { create("dev") { dimension = "environment" applicationIdSuffix = ".dev" versionNameSuffix = "-dev" // Different config values per flavor buildConfigField("String", "API_BASE_URL", "\"https://dev-api.example.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "true") // Different resources resValue("string", "app_name", "MyApp Dev") } create("staging") { dimension = "environment" applicationIdSuffix = ".staging" versionNameSuffix = "-staging" buildConfigField("String", "API_BASE_URL", "\"https://staging-api.example.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "true") resValue("string", "app_name", "MyApp Staging") } create("prod") { dimension = "environment" // No suffix for production buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"") buildConfigField("Boolean", "ENABLE_LOGGING", "false") resValue("string", "app_name", "MyApp") } } buildTypes { debug { isDebuggable = true isMinifyEnabled = false } release { isDebuggable = false isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } ``` **Build Variant Naming**: `{flavor}{BuildType}` → e.g., `devDebug`, `prodRelease` **Gradle Build Commands**: ```bash # List all available build variants ./gradlew tasks --group="build" # Build specific variant (flavor + buildType) ./gradlew assembleDevDebug # Dev flavor, Debug build ./gradlew assembleStagingDebug # Staging flavor, Debug build ./gradlew assembleProdRelease # Prod flavor, Release build # Build all variants of a specific flavor ./gradlew assembleDev # All Dev variants (debug + release) ./gradlew assembleProd # All Prod variants # Build all variants of a specific build type ./gradlew assembleDebug # All flavors, Debug build ./gradlew assembleRelease # All flavors, Release build # Install specific variant to device ./gradlew installDevDebug ./gradlew installProdRelease # Build and install in one command ./gradlew installDevDebug && adb shell am start -n com.example.myapp.dev/.MainActivity ``` **Access BuildConfig in Code**: > **Note**: Starting from AGP 8.0, `BuildConfig` is no longer generated by default. You must explicitly enable it in your `build.gradle.kts`: > ```kotlin > android { > buildFeatures { > buildConfig = true > } > } > ``` ```kotlin // Use build config values in your code val apiUrl = BuildConfig.API_BASE_URL val isLoggingEnabled = BuildConfig.ENABLE_LOGGING if (BuildConfig.DEBUG) { // Debug-only code } ``` **Flavor-Specific Source Sets**: ``` app/src/ ├── main/ # Shared code for all flavors ├── dev/ # Dev-only code and resources │ ├── java/ │ └── res/ ├── staging/ # Staging-only code and resources ├── prod/ # Prod-only code and resources ├── debug/ # Debug build type code └── release/ # Release build type code ``` **Multiple Flavor Dimensions** (e.g., environment + tier): ```kotlin android { flavorDimensions += listOf("environment", "tier") productFlavors { create("dev") { dimension = "environment" } create("prod") { dimension = "environment" } create("free") { dimension = "tier" } create("paid") { dimension = "tier" } } } // Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc. ``` --- ## 3. Kotlin Development Standards ### 3.1 Naming Conventions | Type | Convention | Example | |------|------------|---------| | Class/Interface | PascalCase | `UserRepository`, `MainActivity` | | Function/Variable | camelCase | `getUserName()`, `isLoading` | | Constant | SCREAMING_SNAKE | `MAX_RETRY_COUNT` | | Package | lowercase | `com.example.myapp` | | Composable | PascalCase | `@Composable fun UserCard()` | ### 3.2 Code Standards (Important) **Null Safety**: ```kotlin // ❌ Avoid: Non-null assertion !! (may crash) val name = user!!.name // ✅ Recommended: Safe call + default value val name = user?.name ?: "Unknown" // ✅ Recommended: let handling user?.let { processUser(it) } ``` **Exception Handling**: ```kotlin // ❌ Avoid: Random try-catch in business layer swallowing exceptions fun loadData() { try { val data = api.fetch() } catch (e: Exception) { // Swallowing exception, hard to debug } } // ✅ Recommended: Let exceptions propagate, handle at appropriate layer suspend fun loadData(): Result<Data> { return try { Result.success(api.fetch()) } catch (e: Exception) { Result.failure(e) // Wrap and return, let caller decide handling } } // ✅ Recommended: Unified handling in ViewModel viewModelScope.launch { runCatching { repository.loadData() } .onSuccess { _uiState.value = UiState.Success(it) } .onFailure { _uiState.value = UiState.Error(it.message) } } ``` ### 3.3 Threading & Coroutines (Critical) **Thread Selection Principles**: | Operation Type | Thread | Description | |----------------|--------|-------------| | UI Updates | `Dispatchers.Main` | Update View, State, LiveData | | Network Requests | `Dispatchers.IO` | HTTP calls, API requests | | File I/O | `Dispatchers.IO` | Local storage, database operations | | Compute Intensive | `Dispatchers.Default` | JSON parsing, sorting, encryption | **Correct Usage**: ```kotlin // In ViewModel viewModelScope.launch { // Default Main thread, can update UI State _uiState.value = UiState.Loading // Switch to IO thread for network request val result = withContext(Dispatchers.IO) { repository.fetchData() } // Automatically returns to Main thread, update UI _uiState.value = UiState.Success(result) } // In Repository (suspend functions should be main-safe) suspend fun fetchData(): Data = withContext(Dispatchers.IO) { api.getData() } ``` **Common Mistakes**: ```kotlin // ❌ Wrong: Updating UI on IO thread viewModelScope.launch(Dispatchers.IO) { val data = api.fetch() _uiState.value = data // Crash or warning! } // ❌ Wrong: Executing time-consuming operation on Main thread viewModelScope.launch { val data = api.fetch() // Blocking main thread! ANR } // ✅ Correct: Fetch on IO, update on Main viewModelScope.launch { val data = withContext(Dispatchers.IO) { api.fetch() } _uiState.value = data } ``` ### 3.4 Visibility Rules ```kotlin // Default is public, declare explicitly when needed class UserRepository { // public private val cache = mutableMapOf<String, User>() // Visible only within class internal fun clearCache() {} // Visible only within module } // data class properties are public by default, be careful when used across modules data class User( val id: String, // public val name: String ) ``` ### 3.5 Common Syntax Pitfalls ```kotlin // ❌ Wrong: Accessing uninitialized lateinit class MyViewModel : ViewModel() { lateinit var data: String fun process() = data.length // May crash } // ✅ Correct: Use nullable or default value class MyViewModel : ViewModel() { var data: String? = null fun process() = data?.length ?: 0 } // ❌ Wrong: Using return in lambda list.forEach { item -> if (item.isEmpty()) return // Returns from outer function! } // ✅ Correct: Use return@forEach list.forEach { item -> if (item.isEmpty()) return@forEach } ``` ### 3.6 Server Response Data Class Fields Must Be Nullable ```kotlin // ❌ Wrong: Fields declared as non-null (server may not return them) data class UserResponse( val id: String = "", val name: String = "", val avatar: String = "" ) // ✅ Correct: All fields declared as nullable data class UserResponse( @SerializedName("id") val id: String? = null, @SerializedName("name") val name: String? = null, @SerializedName("avatar") val avatar: String? = null ) ``` ### 3.7 Lifecycle Resource Management ```kotlin // ❌ Wrong: Only adding Observer, not removing class MyView : View { override fun onAttachedToWindow() { super.onAttachedToWindow() activity?.lifecycle?.addObserver(this) } // Memory leak! } // ✅ Correct: Paired add and remove class MyView : View { override fun onAttachedToWindow() { super.onAttachedToWindow() activity?.lifecycle?.addObserver(this) } override fun onDetachedFromWindow() { activity?.lifecycle?.removeObserver(this) super.onDetachedFromWindow() } } ``` ### 3.8 Logging Level Usage ```kotlin import android.util.Log // Info: Key checkpoints in normal flow Log.i(TAG, "loadData: started, userId = $userId") // Warning: Abnormal but recoverable situations Log.w(TAG, "loadData: cache miss, fallback to network") // Error: Failure/error situations Log.e(TAG, "loadData failed: ${error.message}") ``` | Level | Use Case | |-------|----------| | `i` (Info) | Normal flow, method entry, key parameters | | `w` (Warning) | Recoverable exceptions, fallback handling, null returns |
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看