[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-minimax-android-native-dev":3,"mdc--y2vgn3-key":40,"related-org-minimax-android-native-dev":7127,"related-repo-minimax-android-native-dev":7313},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":29,"repoUrl":30,"updatedAt":31,"license":32,"forks":33,"topics":34,"repo":35,"sourceUrl":38,"mdContent":39},"android-native-dev","develop Android native applications","Android native application development and UI design guide. Covers Material Design 3, Kotlin\u002FCompose development, project configuration, accessibility, and build troubleshooting. Read this before Android native application development.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"minimax","MiniMax","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fminimax.jpg","MiniMax-AI",[13,17,20,23,26],{"name":14,"slug":15,"type":16},"Kotlin","kotlin","tag",{"name":18,"slug":19,"type":16},"Android","android",{"name":21,"slug":22,"type":16},"Accessibility","accessibility",{"name":24,"slug":25,"type":16},"Mobile","mobile",{"name":27,"slug":28,"type":16},"UI Components","ui-components",13030,"https:\u002F\u002Fgithub.com\u002FMiniMax-AI\u002Fskills","2026-07-13T06:16:54.247834","MIT",1118,[],{"repoUrl":30,"stars":29,"forks":33,"topics":36,"description":37},[],null,"https:\u002F\u002Fgithub.com\u002FMiniMax-AI\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fandroid-native-dev","---\nname: android-native-dev\ndescription: Android native application development and UI design guide. Covers Material Design 3, Kotlin\u002FCompose development, project configuration, accessibility, and build troubleshooting. Read this before Android native application development.\nlicense: MIT\nmetadata:\n  version: \"1.0.0\"\n  category: mobile\n  sources:\n    - Material Design 3 Guidelines (material.io)\n    - Android Developer Documentation (developer.android.com)\n    - Google Play Quality Guidelines\n    - WCAG Accessibility Guidelines\n---\n\n## 1. Project Scenario Assessment\n\nBefore starting development, assess the current project state:\n\n| Scenario | Characteristics | Approach |\n|----------|-----------------|----------|\n| **Empty Directory** | No files present | Full initialization required, including Gradle Wrapper |\n| **Has Gradle Wrapper** | `gradlew` and `gradle\u002Fwrapper\u002F` exist | Use `.\u002Fgradlew` directly for builds |\n| **Android Studio Project** | Complete project structure, may lack wrapper | Check wrapper, run `gradle wrapper` if needed |\n| **Incomplete Project** | Partial files present | Check missing files, complete configuration |\n\n**Key Principles**:\n- Before writing business logic, ensure `.\u002Fgradlew assembleDebug` succeeds\n- If `gradle.properties` is missing, create it first and configure AndroidX\n\n### 1.1 Required Files Checklist\n\n```\nMyApp\u002F\n├── gradle.properties          # Configure AndroidX and other settings\n├── settings.gradle.kts\n├── build.gradle.kts           # Root level\n├── gradle\u002Fwrapper\u002F\n│   └── gradle-wrapper.properties\n├── app\u002F\n│   ├── build.gradle.kts       # Module level\n│   └── src\u002Fmain\u002F\n│       ├── AndroidManifest.xml\n│       ├── java\u002Fcom\u002Fexample\u002Fmyapp\u002F\n│       │   └── MainActivity.kt\n│       └── res\u002F\n│           ├── values\u002F\n│           │   ├── strings.xml\n│           │   ├── colors.xml\n│           │   └── themes.xml\n│           └── mipmap-*\u002F       # App icons\n```\n\n---\n\n## 2. Project Configuration\n\n### 2.1 gradle.properties\n\n```properties\n# Required configuration\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n\n# Build optimization\norg.gradle.parallel=true\nkotlin.code.style=official\n\n# JVM memory settings (adjust based on project size)\n# Small projects: 2048m, Medium: 4096m, Large: 8192m+\n# org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8\n```\n\n> **Note**: If you encounter `OutOfMemoryError` during build, increase `-Xmx` value. Large projects with many dependencies may require 8GB or more.\n\n### 2.2 Dependency Declaration Standards\n\n```kotlin\ndependencies {\n    \u002F\u002F Use BOM to manage Compose versions\n    implementation(platform(\"androidx.compose:compose-bom:2024.02.00\"))\n    implementation(\"androidx.compose.ui:ui\")\n    implementation(\"androidx.compose.material3:material3\")\n    \n    \u002F\u002F Activity & ViewModel\n    implementation(\"androidx.activity:activity-compose:1.8.2\")\n    implementation(\"androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0\")\n}\n```\n\n### 2.3 Build Variants & Product Flavors\n\nProduct Flavors allow you to create different versions of your app (e.g., free\u002Fpaid, dev\u002Fstaging\u002Fprod).\n\n**Configuration in app\u002Fbuild.gradle.kts**:\n\n```kotlin\nandroid {\n    \u002F\u002F Define flavor dimensions\n    flavorDimensions += \"environment\"\n    \n    productFlavors {\n        create(\"dev\") {\n            dimension = \"environment\"\n            applicationIdSuffix = \".dev\"\n            versionNameSuffix = \"-dev\"\n            \n            \u002F\u002F Different config values per flavor\n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fdev-api.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"true\")\n            \n            \u002F\u002F Different resources\n            resValue(\"string\", \"app_name\", \"MyApp Dev\")\n        }\n        \n        create(\"staging\") {\n            dimension = \"environment\"\n            applicationIdSuffix = \".staging\"\n            versionNameSuffix = \"-staging\"\n            \n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fstaging-api.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"true\")\n            resValue(\"string\", \"app_name\", \"MyApp Staging\")\n        }\n        \n        create(\"prod\") {\n            dimension = \"environment\"\n            \u002F\u002F No suffix for production\n            \n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fapi.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"false\")\n            resValue(\"string\", \"app_name\", \"MyApp\")\n        }\n    }\n    \n    buildTypes {\n        debug {\n            isDebuggable = true\n            isMinifyEnabled = false\n        }\n        release {\n            isDebuggable = false\n            isMinifyEnabled = true\n            proguardFiles(getDefaultProguardFile(\"proguard-android-optimize.txt\"), \"proguard-rules.pro\")\n        }\n    }\n}\n```\n\n**Build Variant Naming**: `{flavor}{BuildType}` → e.g., `devDebug`, `prodRelease`\n\n**Gradle Build Commands**:\n\n```bash\n# List all available build variants\n.\u002Fgradlew tasks --group=\"build\"\n\n# Build specific variant (flavor + buildType)\n.\u002Fgradlew assembleDevDebug        # Dev flavor, Debug build\n.\u002Fgradlew assembleStagingDebug    # Staging flavor, Debug build\n.\u002Fgradlew assembleProdRelease     # Prod flavor, Release build\n\n# Build all variants of a specific flavor\n.\u002Fgradlew assembleDev             # All Dev variants (debug + release)\n.\u002Fgradlew assembleProd            # All Prod variants\n\n# Build all variants of a specific build type\n.\u002Fgradlew assembleDebug           # All flavors, Debug build\n.\u002Fgradlew assembleRelease         # All flavors, Release build\n\n# Install specific variant to device\n.\u002Fgradlew installDevDebug\n.\u002Fgradlew installProdRelease\n\n# Build and install in one command\n.\u002Fgradlew installDevDebug && adb shell am start -n com.example.myapp.dev\u002F.MainActivity\n```\n\n**Access BuildConfig in Code**:\n\n> **Note**: Starting from AGP 8.0, `BuildConfig` is no longer generated by default. You must explicitly enable it in your `build.gradle.kts`:\n> ```kotlin\n> android {\n>     buildFeatures {\n>         buildConfig = true\n>     }\n> }\n> ```\n\n```kotlin\n\u002F\u002F Use build config values in your code\nval apiUrl = BuildConfig.API_BASE_URL\nval isLoggingEnabled = BuildConfig.ENABLE_LOGGING\n\nif (BuildConfig.DEBUG) {\n    \u002F\u002F Debug-only code\n}\n```\n\n**Flavor-Specific Source Sets**:\n\n```\napp\u002Fsrc\u002F\n├── main\u002F           # Shared code for all flavors\n├── dev\u002F            # Dev-only code and resources\n│   ├── java\u002F\n│   └── res\u002F\n├── staging\u002F        # Staging-only code and resources\n├── prod\u002F           # Prod-only code and resources\n├── debug\u002F          # Debug build type code\n└── release\u002F        # Release build type code\n```\n\n**Multiple Flavor Dimensions** (e.g., environment + tier):\n\n```kotlin\nandroid {\n    flavorDimensions += listOf(\"environment\", \"tier\")\n    \n    productFlavors {\n        create(\"dev\") { dimension = \"environment\" }\n        create(\"prod\") { dimension = \"environment\" }\n        \n        create(\"free\") { dimension = \"tier\" }\n        create(\"paid\") { dimension = \"tier\" }\n    }\n}\n\u002F\u002F Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc.\n```\n\n---\n\n## 3. Kotlin Development Standards\n\n### 3.1 Naming Conventions\n\n| Type | Convention | Example |\n|------|------------|---------|\n| Class\u002FInterface | PascalCase | `UserRepository`, `MainActivity` |\n| Function\u002FVariable | camelCase | `getUserName()`, `isLoading` |\n| Constant | SCREAMING_SNAKE | `MAX_RETRY_COUNT` |\n| Package | lowercase | `com.example.myapp` |\n| Composable | PascalCase | `@Composable fun UserCard()` |\n\n### 3.2 Code Standards (Important)\n\n**Null Safety**:\n```kotlin\n\u002F\u002F ❌ Avoid: Non-null assertion !! (may crash)\nval name = user!!.name\n\n\u002F\u002F ✅ Recommended: Safe call + default value\nval name = user?.name ?: \"Unknown\"\n\n\u002F\u002F ✅ Recommended: let handling\nuser?.let { processUser(it) }\n```\n\n**Exception Handling**:\n```kotlin\n\u002F\u002F ❌ Avoid: Random try-catch in business layer swallowing exceptions\nfun loadData() {\n    try {\n        val data = api.fetch()\n    } catch (e: Exception) {\n        \u002F\u002F Swallowing exception, hard to debug\n    }\n}\n\n\u002F\u002F ✅ Recommended: Let exceptions propagate, handle at appropriate layer\nsuspend fun loadData(): Result\u003CData> {\n    return try {\n        Result.success(api.fetch())\n    } catch (e: Exception) {\n        Result.failure(e)  \u002F\u002F Wrap and return, let caller decide handling\n    }\n}\n\n\u002F\u002F ✅ Recommended: Unified handling in ViewModel\nviewModelScope.launch {\n    runCatching { repository.loadData() }\n        .onSuccess { _uiState.value = UiState.Success(it) }\n        .onFailure { _uiState.value = UiState.Error(it.message) }\n}\n```\n\n### 3.3 Threading & Coroutines (Critical)\n\n**Thread Selection Principles**:\n\n| Operation Type | Thread | Description |\n|----------------|--------|-------------|\n| UI Updates | `Dispatchers.Main` | Update View, State, LiveData |\n| Network Requests | `Dispatchers.IO` | HTTP calls, API requests |\n| File I\u002FO | `Dispatchers.IO` | Local storage, database operations |\n| Compute Intensive | `Dispatchers.Default` | JSON parsing, sorting, encryption |\n\n**Correct Usage**:\n```kotlin\n\u002F\u002F In ViewModel\nviewModelScope.launch {\n    \u002F\u002F Default Main thread, can update UI State\n    _uiState.value = UiState.Loading\n    \n    \u002F\u002F Switch to IO thread for network request\n    val result = withContext(Dispatchers.IO) {\n        repository.fetchData()\n    }\n    \n    \u002F\u002F Automatically returns to Main thread, update UI\n    _uiState.value = UiState.Success(result)\n}\n\n\u002F\u002F In Repository (suspend functions should be main-safe)\nsuspend fun fetchData(): Data = withContext(Dispatchers.IO) {\n    api.getData()\n}\n```\n\n**Common Mistakes**:\n```kotlin\n\u002F\u002F ❌ Wrong: Updating UI on IO thread\nviewModelScope.launch(Dispatchers.IO) {\n    val data = api.fetch()\n    _uiState.value = data  \u002F\u002F Crash or warning!\n}\n\n\u002F\u002F ❌ Wrong: Executing time-consuming operation on Main thread\nviewModelScope.launch {\n    val data = api.fetch()  \u002F\u002F Blocking main thread! ANR\n}\n\n\u002F\u002F ✅ Correct: Fetch on IO, update on Main\nviewModelScope.launch {\n    val data = withContext(Dispatchers.IO) { api.fetch() }\n    _uiState.value = data\n}\n```\n\n### 3.4 Visibility Rules\n\n```kotlin\n\u002F\u002F Default is public, declare explicitly when needed\nclass UserRepository {           \u002F\u002F public\n    private val cache = mutableMapOf\u003CString, User>()  \u002F\u002F Visible only within class\n    internal fun clearCache() {} \u002F\u002F Visible only within module\n}\n\n\u002F\u002F data class properties are public by default, be careful when used across modules\ndata class User(\n    val id: String,       \u002F\u002F public\n    val name: String\n)\n```\n\n### 3.5 Common Syntax Pitfalls\n\n```kotlin\n\u002F\u002F ❌ Wrong: Accessing uninitialized lateinit\nclass MyViewModel : ViewModel() {\n    lateinit var data: String\n    fun process() = data.length  \u002F\u002F May crash\n}\n\n\u002F\u002F ✅ Correct: Use nullable or default value\nclass MyViewModel : ViewModel() {\n    var data: String? = null\n    fun process() = data?.length ?: 0\n}\n\n\u002F\u002F ❌ Wrong: Using return in lambda\nlist.forEach { item ->\n    if (item.isEmpty()) return  \u002F\u002F Returns from outer function!\n}\n\n\u002F\u002F ✅ Correct: Use return@forEach\nlist.forEach { item ->\n    if (item.isEmpty()) return@forEach\n}\n```\n\n### 3.6 Server Response Data Class Fields Must Be Nullable\n\n```kotlin\n\u002F\u002F ❌ Wrong: Fields declared as non-null (server may not return them)\ndata class UserResponse(\n    val id: String = \"\",\n    val name: String = \"\",\n    val avatar: String = \"\"\n)\n\n\u002F\u002F ✅ Correct: All fields declared as nullable\ndata class UserResponse(\n    @SerializedName(\"id\")\n    val id: String? = null,\n    @SerializedName(\"name\")\n    val name: String? = null,\n    @SerializedName(\"avatar\")\n    val avatar: String? = null\n)\n```\n\n### 3.7 Lifecycle Resource Management\n\n```kotlin\n\u002F\u002F ❌ Wrong: Only adding Observer, not removing\nclass MyView : View {\n    override fun onAttachedToWindow() {\n        super.onAttachedToWindow()\n        activity?.lifecycle?.addObserver(this)\n    }\n    \u002F\u002F Memory leak!\n}\n\n\u002F\u002F ✅ Correct: Paired add and remove\nclass MyView : View {\n    override fun onAttachedToWindow() {\n        super.onAttachedToWindow()\n        activity?.lifecycle?.addObserver(this)\n    }\n\n    override fun onDetachedFromWindow() {\n        activity?.lifecycle?.removeObserver(this)\n        super.onDetachedFromWindow()\n    }\n}\n```\n\n### 3.8 Logging Level Usage\n\n```kotlin\nimport android.util.Log\n\n\u002F\u002F Info: Key checkpoints in normal flow\nLog.i(TAG, \"loadData: started, userId = $userId\")\n\n\u002F\u002F Warning: Abnormal but recoverable situations\nLog.w(TAG, \"loadData: cache miss, fallback to network\")\n\n\u002F\u002F Error: Failure\u002Ferror situations\nLog.e(TAG, \"loadData failed: ${error.message}\")\n```\n\n| Level | Use Case |\n|-------|----------|\n| `i` (Info) | Normal flow, method entry, key parameters |\n| `w` (Warning) | Recoverable exceptions, fallback handling, null returns |\n| `e` (Error) | Request failures, caught exceptions, unrecoverable errors |\n\n---\n\n## 4. Jetpack Compose Standards\n\n### 4.1 @Composable Context Rules\n\n```kotlin\n\u002F\u002F ❌ Wrong: Calling Composable from non-Composable function\nfun showError(message: String) {\n    Text(message)  \u002F\u002F Compile error!\n}\n\n\u002F\u002F ✅ Correct: Mark as @Composable\n@Composable\nfun ErrorMessage(message: String) {\n    Text(message)\n}\n\n\u002F\u002F ❌ Wrong: Using suspend outside LaunchedEffect\n@Composable\nfun MyScreen() {\n    val data = fetchData()  \u002F\u002F Error!\n}\n\n\u002F\u002F ✅ Correct: Use LaunchedEffect\n@Composable\nfun MyScreen() {\n    var data by remember { mutableStateOf\u003CData?>(null) }\n    LaunchedEffect(Unit) {\n        data = fetchData()\n    }\n}\n```\n\n### 4.2 State Management\n\n```kotlin\n\u002F\u002F Basic State\nvar count by remember { mutableStateOf(0) }\n\n\u002F\u002F Derived State (avoid redundant computation)\nval isEven by remember { derivedStateOf { count % 2 == 0 } }\n\n\u002F\u002F Persist across recomposition (e.g., scroll position)\nval scrollState = rememberScrollState()\n\n\u002F\u002F State in ViewModel\nclass MyViewModel : ViewModel() {\n    private val _uiState = MutableStateFlow(UiState())\n    val uiState: StateFlow\u003CUiState> = _uiState.asStateFlow()\n}\n```\n\n### 4.3 Common Compose Mistakes\n\n```kotlin\n\u002F\u002F ❌ Wrong: Creating objects in Composable (created on every recomposition)\n@Composable\nfun MyScreen() {\n    val viewModel = MyViewModel()  \u002F\u002F Wrong!\n}\n\n\u002F\u002F ✅ Correct: Use viewModel() or remember\n@Composable\nfun MyScreen(viewModel: MyViewModel = viewModel()) {\n    \u002F\u002F ...\n}\n```\n\n---\n\n## 5. Resources & Icons\n\n### 5.1 App Icon Requirements\n\nMust provide multi-resolution icons:\n\n| Directory | Size | Purpose |\n|-----------|------|---------|\n| mipmap-mdpi | 48x48 | Baseline |\n| mipmap-hdpi | 72x72 | 1.5x |\n| mipmap-xhdpi | 96x96 | 2x |\n| mipmap-xxhdpi | 144x144 | 3x |\n| mipmap-xxxhdpi | 192x192 | 4x |\n\nRecommended: Use Adaptive Icon (Android 8+):\n\n```xml\n\u003C!-- res\u002Fmipmap-anydpi-v26\u002Fic_launcher.xml -->\n\u003Cadaptive-icon>\n    \u003Cbackground android:drawable=\"@color\u002Fic_launcher_background\"\u002F>\n    \u003Cforeground android:drawable=\"@mipmap\u002Fic_launcher_foreground\"\u002F>\n\u003C\u002Fadaptive-icon>\n```\n\n### 5.2 Resource Naming Conventions\n\n| Type | Prefix | Example |\n|------|--------|---------|\n| Layout | layout_ | `layout_main.xml` |\n| Image | ic_, img_, bg_ | `ic_user.png` |\n| Color | color_ | `color_primary` |\n| String | - | `app_name`, `btn_submit` |\n\n### 5.3 Avoid Android Reserved Names (Important)\n\nVariable names, resource IDs, colors, icons, and XML elements **must not** use Android reserved words or system resource names. Using reserved names causes build errors or resource conflicts.\n\n**Common Reserved Names to Avoid**:\n\n| Category | Reserved Names (Do NOT Use) |\n|----------|----------------------------|\n| Colors | `background`, `foreground`, `transparent`, `white`, `black` |\n| Icons\u002FDrawables | `icon`, `logo`, `image`, `drawable` |\n| Views | `view`, `text`, `button`, `layout`, `container` |\n| Attributes | `id`, `name`, `type`, `style`, `theme`, `color` |\n| System | `app`, `android`, `content`, `data`, `action` |\n\n**Examples**:\n\n```xml\n\u003C!-- ❌ Wrong: Using reserved names -->\n\u003Ccolor name=\"background\">#FFFFFF\u003C\u002Fcolor>\n\u003Ccolor name=\"icon\">#000000\u003C\u002Fcolor>\n\n\u003C!-- ✅ Correct: Add prefix or specific naming -->\n\u003Ccolor name=\"app_background\">#FFFFFF\u003C\u002Fcolor>\n\u003Ccolor name=\"icon_primary\">#000000\u003C\u002Fcolor>\n```\n\n```kotlin\n\u002F\u002F ❌ Wrong: Variable names conflict with system\nval icon = R.drawable.my_icon\nval background = Color.White\n\n\u002F\u002F ✅ Correct: Use descriptive names\nval appIcon = R.drawable.my_icon\nval screenBackground = Color.White\n```\n\n```xml\n\u003C!-- ❌ Wrong: Drawable name conflicts -->\n\u003CImageView android:src=\"@drawable\u002Ficon\" \u002F>\n\n\u003C!-- ✅ Correct: Add prefix -->\n\u003CImageView android:src=\"@drawable\u002Fic_home\" \u002F>\n```\n\n---\n\n## 6. Build Error Diagnosis & Fixes\n\n### 6.1 Common Error Quick Reference\n\n| Error Keyword | Cause | Fix |\n|---------------|-------|-----|\n| `Unresolved reference` | Missing import or undefined | Check imports, verify dependencies |\n| `Type mismatch` | Type incompatibility | Check parameter types, add conversion |\n| `Cannot access` | Visibility issue | Check public\u002Fprivate\u002Finternal |\n| `@Composable invocations` | Composable context error | Ensure caller is also @Composable |\n| `Duplicate class` | Dependency conflict | Use `.\u002Fgradlew dependencies` to investigate |\n| `AAPT: error` | Resource file error | Check XML syntax and resource references |\n\n### 6.2 Fix Best Practices\n\n1. **Read the complete error message first**: Locate file and line number\n2. **Check recent changes**: Problems usually in latest modifications\n3. **Clean Build**: `.\u002Fgradlew clean assembleDebug`\n4. **Check dependency versions**: Version conflicts are common causes\n5. **Refresh dependencies if needed**: Clear cache and rebuild\n\n### 6.3 Debugging Commands\n\n```bash\n# Clean and build\n.\u002Fgradlew clean assembleDebug\n\n# View dependency tree (investigate conflicts)\n.\u002Fgradlew :app:dependencies\n\n# View detailed errors\n.\u002Fgradlew assembleDebug --stacktrace\n\n# Refresh dependencies\n.\u002Fgradlew --refresh-dependencies\n```\n\n---\n\n## 7. Material Design 3 Guidelines\n\nReview Android UI files for compliance with Material Design 3 Guidelines and Android best practices.\n\n### Design Philosophy\n\n#### M3 Core Principles\n\n| Principle | Description |\n|-----------|-------------|\n| **Personal** | Dynamic color based on user preferences and wallpaper |\n| **Adaptive** | Responsive across all screen sizes and form factors |\n| **Expressive** | Bold colors and typography with personality |\n| **Accessible** | Inclusive design for all users |\n\n#### M3 Expressive (Latest)\n\nThe latest evolution adds emotion-driven UX through:\n- Vibrant, dynamic colors\n- Intuitive motion physics\n- Adaptive components\n- Flexible typography\n- Contrasting shapes (35 new shape options)\n\n### App Style Selection\n\n**Critical Decision**: Match visual style to app category and target audience.\n\n| App Category | Visual Style | Key Characteristics |\n|--------------|--------------|---------------------|\n| Utility\u002FTool | Minimalist | Clean, efficient, neutral colors |\n| Finance\u002FBanking | Professional Trust | Conservative colors, security-focused |\n| Health\u002FWellness | Calm & Natural | Soft colors, organic shapes |\n| Kids (3-5) | Playful Simple | Bright colors, large targets (56dp+) |\n| Kids (6-12) | Fun & Engaging | Vibrant, gamified feedback |\n| Social\u002FEntertainment | Expressive | Brand-driven, gesture-rich |\n| Productivity | Clean & Focused | Minimal, high contrast |\n| E-commerce | Conversion-focused | Clear CTAs, scannable |\n\nSee [Design Style Guide](references\u002Fdesign-style-guide.md) for detailed style profiles.\n\n### Quick Reference: Key Specifications\n\n#### Color Contrast Requirements\n\n| Element | Minimum Ratio |\n|---------|---------------|\n| Body text | **4.5:1** |\n| Large text (18sp+) | **3:1** |\n| UI components | **3:1** |\n\n#### Touch Targets\n\n| Type | Size |\n|------|------|\n| Minimum | 48 × 48dp |\n| Recommended (primary actions) | 56 × 56dp |\n| Kids apps | 56dp+ |\n| Spacing between targets | 8dp minimum |\n\n#### 8dp Grid System\n\n| Token | Value | Usage |\n|-------|-------|-------|\n| xs | 4dp | Icon padding |\n| sm | 8dp | Tight spacing |\n| md | 16dp | Default padding |\n| lg | 24dp | Section spacing |\n| xl | 32dp | Large gaps |\n| xxl | 48dp | Screen margins |\n\n#### Typography Scale (Summary)\n\n| Category | Sizes |\n|----------|-------|\n| Display | 57sp, 45sp, 36sp |\n| Headline | 32sp, 28sp, 24sp |\n| Title | 22sp, 16sp, 14sp |\n| Body | 16sp, 14sp, 12sp |\n| Label | 14sp, 12sp, 11sp |\n\n#### Animation Duration\n\n| Type | Duration |\n|------|----------|\n| Micro (ripples) | 50-100ms |\n| Short (simple) | 100-200ms |\n| Medium (expand\u002Fcollapse) | 200-300ms |\n| Long (complex) | 300-500ms |\n\n#### Component Dimensions\n\n| Component | Height | Min Width |\n|-----------|--------|-----------|\n| Button | 40dp | 64dp |\n| FAB | 56dp | 56dp |\n| Text Field | 56dp | 280dp |\n| App Bar | 64dp | - |\n| Bottom Nav | 80dp | - |\n\n### Anti-Patterns (Must Avoid)\n\n#### UI Anti-Patterns\n- More than 5 bottom navigation items\n- Multiple FABs on same screen\n- Touch targets smaller than 48dp\n- Inconsistent spacing (non-8dp multiples)\n- Missing dark theme support\n- Text on colored backgrounds without contrast check\n\n#### Performance Anti-Patterns\n- Startup time > 2 seconds without progress indicator\n- Frame rate \u003C 60 FPS (> 16ms per frame)\n- Crash rate > 1.09% (Google Play threshold)\n- ANR rate > 0.47% (Google Play threshold)\n\n#### Accessibility Anti-Patterns\n- Missing contentDescription on interactive elements\n- Element type in labels (e.g., \"Save button\" instead of \"Save\")\n- Complex gestures in kids apps\n- Text-only buttons for non-readers\n\n### Review Checklist\n\n- [ ] 8dp spacing grid compliance\n- [ ] 48dp minimum touch targets\n- [ ] Proper typography scale usage\n- [ ] Color contrast compliance (4.5:1+ for text)\n- [ ] Dark theme support\n- [ ] contentDescription on all interactive elements\n- [ ] Startup \u003C 2 seconds or shows progress\n- [ ] Visual style matches app category\n\n### Design References\n\n| Topic | Reference |\n|-------|-----------|\n| Colors, Typography, Spacing, Shapes | [Visual Design](references\u002Fvisual-design.md) |\n| Animation & Transitions | [Motion System](references\u002Fmotion-system.md) |\n| Accessibility Guidelines | [Accessibility](references\u002Faccessibility.md) |\n| Large Screens & Foldables | [Adaptive Screens](references\u002Fadaptive-screens.md) |\n| Android Vitals & Performance | [Performance & Stability](references\u002Fperformance-stability.md) |\n| Privacy & Security | [Privacy & Security](references\u002Fprivacy-security.md) |\n| Audio, Video, Notifications | [Functional Requirements](references\u002Ffunctional-requirements.md) |\n| App Style by Category | [Design Style Guide](references\u002Fdesign-style-guide.md) |\n\n---\n\n## 8. Testing\n\n> **Note**: Only add test dependencies when the user explicitly asks for testing.\n\nA well-tested Android app uses layered testing: fast local unit tests for logic, instrumentation tests for UI and integration, and Gradle Managed Devices to run emulators reproducibly on any machine — including CI.\n\n### 8.1 Test Dependencies\n\nBefore adding test dependencies, inspect the project's existing versions to avoid conflicts:\n\n1. Check `gradle\u002Flibs.versions.toml` — if present, add test deps using the project's version catalog style\n2. Check existing `build.gradle.kts` for already-pinned dependency versions\n3. Match version families using the table below\n\n**Version Alignment Rules**:\n\n| Test Dependency                              | Must Align With                                  | How to Check                                                          |\n|----------------------------------------------|--------------------------------------------------|-----------------------------------------------------------------------|\n| `kotlinx-coroutines-test`                    | Project's `kotlinx-coroutines-core` version      | Search for `kotlinx-coroutines` in build files or version catalog     |\n| `compose-ui-test-junit4`                     | Project's Compose BOM or `compose-compiler`      | Search for `compose-bom` or `compose.compiler` in build files         |\n| `espresso-*`                                 | All Espresso artifacts must use the same version  | Search for `espresso` in build files                                  |\n| `androidx.test:runner`, `rules`, `ext:junit` | Should use compatible AndroidX Test versions      | Search for `androidx.test` in build files                             |\n| `mockk`                                      | Must support the project's Kotlin version         | Check `kotlin` version in root `build.gradle.kts` or version catalog |\n\n**Dependencies Reference** — add only the groups you need:\n\n```kotlin\ndependencies {\n    \u002F\u002F --- Local unit tests (src\u002Ftest\u002F) ---\n    testImplementation(\"junit:junit:\u003Cversion>\")                          \u002F\u002F 4.13.2+\n    testImplementation(\"org.robolectric:robolectric:\u003Cversion>\")          \u002F\u002F 4.16.1+\n    testImplementation(\"io.mockk:mockk:\u003Cversion>\")                      \u002F\u002F match Kotlin version\n    testImplementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-test:\u003Cversion>\")  \u002F\u002F match coroutines-core\n    testImplementation(\"androidx.arch.core:core-testing:\u003Cversion>\")      \u002F\u002F InstantTaskExecutorRule for LiveData\n    testImplementation(\"app.cash.turbine:turbine:\u003Cversion>\")             \u002F\u002F Flow\u002FStateFlow testing\n\n    \u002F\u002F --- Instrumentation tests (src\u002FandroidTest\u002F) ---\n    androidTestImplementation(\"androidx.test.ext:junit:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test:runner:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test:rules:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.espresso:espresso-core:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.espresso:espresso-contrib:\u003Cversion>\")   \u002F\u002F RecyclerView, Drawer\n    androidTestImplementation(\"androidx.test.espresso:espresso-intents:\u003Cversion>\")   \u002F\u002F Intent verification\n    androidTestImplementation(\"androidx.test.espresso:espresso-idling-resource:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.uiautomator:uiautomator:\u003Cversion>\")\n\n    \u002F\u002F --- Compose UI tests (only if project uses Compose) ---\n    androidTestImplementation(\"androidx.compose.ui:ui-test-junit4\")      \u002F\u002F version from Compose BOM\n    debugImplementation(\"androidx.compose.ui:ui-test-manifest\")          \u002F\u002F required for createComposeRule\n}\n```\n\n> **Note**: If the project uses a Compose BOM, `ui-test-junit4` and `ui-test-manifest` don't need explicit versions — the BOM manages them.\n\nEnable Robolectric resource support in the `android` block:\n\n```kotlin\nandroid {\n    testOptions {\n        unitTests.isIncludeAndroidResources = true  \u002F\u002F required for Robolectric\n    }\n}\n```\n\n### 8.2 Testing by Layer\n\n| Layer              | Location           | Runs On                 | Speed                | Use For                                          |\n|--------------------|--------------------|-------------------------|----------------------|--------------------------------------------------|\n| Unit (JUnit)       | `src\u002Ftest\u002F`        | JVM                     | ~ms                  | ViewModels, repos, mappers, validators           |\n| Unit + Robolectric | `src\u002Ftest\u002F`        | JVM + simulated Android | ~100ms               | Code needing Context, resources, SharedPrefs     |\n| Compose UI (local) | `src\u002Ftest\u002F`        | JVM + Robolectric       | ~100ms               | Composable rendering & interaction               |\n| Espresso           | `src\u002FandroidTest\u002F` | Device\u002FEmulator         | ~seconds             | View-based UI flows, Intents, DB integration     |\n| Compose UI (device)| `src\u002FandroidTest\u002F` | Device\u002FEmulator         | ~seconds             | Full Compose UI flows with real rendering        |\n| UI Automator       | `src\u002FandroidTest\u002F` | Device\u002FEmulator         | ~seconds             | System dialogs, notifications, multi-app         |\n| Managed Device     | `src\u002FandroidTest\u002F` | Gradle-managed AVD      | ~minutes (first run) | CI, matrix testing across API levels             |\n\nSee [Testing](references\u002Ftesting.md) for detailed examples, code patterns, and Gradle Managed Device configuration.\n\n### 8.3 Testing Commands\n\n```bash\n# Local unit tests (fast, no emulator)\n.\u002Fgradlew test                          # all modules\n.\u002Fgradlew :app:testDebugUnitTest        # app module, debug variant\n\n# Single test class\n.\u002Fgradlew :app:testDebugUnitTest --tests \"com.example.myapp.CounterViewModelTest\"\n\n# Instrumentation tests (requires device or managed device)\n.\u002Fgradlew connectedDebugAndroidTest     # on connected device\n.\u002Fgradlew pixel6Api34DebugAndroidTest   # on managed device\n\n# Both together\n.\u002Fgradlew test connectedDebugAndroidTest\n\n# Test with coverage report (JaCoCo)\n.\u002Fgradlew testDebugUnitTest jacocoTestReport\n```\n",{"data":41,"body":49},{"name":4,"description":6,"license":32,"metadata":42},{"version":43,"category":25,"sources":44},"1.0.0",[45,46,47,48],"Material Design 3 Guidelines (material.io)","Android Developer Documentation (developer.android.com)","Google Play Quality Guidelines","WCAG Accessibility Guidelines",{"type":50,"children":51},"root",[52,61,67,216,226,257,264,276,280,286,292,402,432,438,526,532,537,546,977,1009,1018,1336,1345,1416,1477,1486,1495,1505,1602,1605,1611,1617,1767,1773,1782,1851,1860,2051,2057,2066,2180,2189,2333,2342,2470,2476,2569,2575,2741,2747,2878,2884,3048,3054,3138,3217,3220,3226,3232,3428,3434,3548,3554,3643,3646,3652,3658,3663,3780,3785,3834,3840,3960,3966,3978,3987,4232,4241,4303,4365,4411,4414,4420,4426,4592,4598,4657,4663,4780,4783,4789,4794,4800,4807,4892,4898,4903,4931,4937,4947,5117,5131,5137,5143,5212,5218,5290,5296,5431,5437,5523,5529,5602,5608,5720,5726,5732,5765,5771,5794,5800,5823,5829,5909,5915,6069,6072,6078,6090,6095,6101,6106,6139,6148,6361,6371,6558,6585,6597,6641,6647,6898,6910,6916,7122],{"type":53,"tag":54,"props":55,"children":57},"element","h2",{"id":56},"_1-project-scenario-assessment",[58],{"type":59,"value":60},"text","1. Project Scenario Assessment",{"type":53,"tag":62,"props":63,"children":64},"p",{},[65],{"type":59,"value":66},"Before starting development, assess the current project state:",{"type":53,"tag":68,"props":69,"children":70},"table",{},[71,95],{"type":53,"tag":72,"props":73,"children":74},"thead",{},[75],{"type":53,"tag":76,"props":77,"children":78},"tr",{},[79,85,90],{"type":53,"tag":80,"props":81,"children":82},"th",{},[83],{"type":59,"value":84},"Scenario",{"type":53,"tag":80,"props":86,"children":87},{},[88],{"type":59,"value":89},"Characteristics",{"type":53,"tag":80,"props":91,"children":92},{},[93],{"type":59,"value":94},"Approach",{"type":53,"tag":96,"props":97,"children":98},"tbody",{},[99,122,166,195],{"type":53,"tag":76,"props":100,"children":101},{},[102,112,117],{"type":53,"tag":103,"props":104,"children":105},"td",{},[106],{"type":53,"tag":107,"props":108,"children":109},"strong",{},[110],{"type":59,"value":111},"Empty Directory",{"type":53,"tag":103,"props":113,"children":114},{},[115],{"type":59,"value":116},"No files present",{"type":53,"tag":103,"props":118,"children":119},{},[120],{"type":59,"value":121},"Full initialization required, including Gradle Wrapper",{"type":53,"tag":76,"props":123,"children":124},{},[125,133,153],{"type":53,"tag":103,"props":126,"children":127},{},[128],{"type":53,"tag":107,"props":129,"children":130},{},[131],{"type":59,"value":132},"Has Gradle Wrapper",{"type":53,"tag":103,"props":134,"children":135},{},[136,143,145,151],{"type":53,"tag":137,"props":138,"children":140},"code",{"className":139},[],[141],{"type":59,"value":142},"gradlew",{"type":59,"value":144}," and ",{"type":53,"tag":137,"props":146,"children":148},{"className":147},[],[149],{"type":59,"value":150},"gradle\u002Fwrapper\u002F",{"type":59,"value":152}," exist",{"type":53,"tag":103,"props":154,"children":155},{},[156,158,164],{"type":59,"value":157},"Use ",{"type":53,"tag":137,"props":159,"children":161},{"className":160},[],[162],{"type":59,"value":163},".\u002Fgradlew",{"type":59,"value":165}," directly for builds",{"type":53,"tag":76,"props":167,"children":168},{},[169,177,182],{"type":53,"tag":103,"props":170,"children":171},{},[172],{"type":53,"tag":107,"props":173,"children":174},{},[175],{"type":59,"value":176},"Android Studio Project",{"type":53,"tag":103,"props":178,"children":179},{},[180],{"type":59,"value":181},"Complete project structure, may lack wrapper",{"type":53,"tag":103,"props":183,"children":184},{},[185,187,193],{"type":59,"value":186},"Check wrapper, run ",{"type":53,"tag":137,"props":188,"children":190},{"className":189},[],[191],{"type":59,"value":192},"gradle wrapper",{"type":59,"value":194}," if needed",{"type":53,"tag":76,"props":196,"children":197},{},[198,206,211],{"type":53,"tag":103,"props":199,"children":200},{},[201],{"type":53,"tag":107,"props":202,"children":203},{},[204],{"type":59,"value":205},"Incomplete Project",{"type":53,"tag":103,"props":207,"children":208},{},[209],{"type":59,"value":210},"Partial files present",{"type":53,"tag":103,"props":212,"children":213},{},[214],{"type":59,"value":215},"Check missing files, complete configuration",{"type":53,"tag":62,"props":217,"children":218},{},[219,224],{"type":53,"tag":107,"props":220,"children":221},{},[222],{"type":59,"value":223},"Key Principles",{"type":59,"value":225},":",{"type":53,"tag":227,"props":228,"children":229},"ul",{},[230,244],{"type":53,"tag":231,"props":232,"children":233},"li",{},[234,236,242],{"type":59,"value":235},"Before writing business logic, ensure ",{"type":53,"tag":137,"props":237,"children":239},{"className":238},[],[240],{"type":59,"value":241},".\u002Fgradlew assembleDebug",{"type":59,"value":243}," succeeds",{"type":53,"tag":231,"props":245,"children":246},{},[247,249,255],{"type":59,"value":248},"If ",{"type":53,"tag":137,"props":250,"children":252},{"className":251},[],[253],{"type":59,"value":254},"gradle.properties",{"type":59,"value":256}," is missing, create it first and configure AndroidX",{"type":53,"tag":258,"props":259,"children":261},"h3",{"id":260},"_11-required-files-checklist",[262],{"type":59,"value":263},"1.1 Required Files Checklist",{"type":53,"tag":265,"props":266,"children":270},"pre",{"className":267,"code":269,"language":59},[268],"language-text","MyApp\u002F\n├── gradle.properties          # Configure AndroidX and other settings\n├── settings.gradle.kts\n├── build.gradle.kts           # Root level\n├── gradle\u002Fwrapper\u002F\n│   └── gradle-wrapper.properties\n├── app\u002F\n│   ├── build.gradle.kts       # Module level\n│   └── src\u002Fmain\u002F\n│       ├── AndroidManifest.xml\n│       ├── java\u002Fcom\u002Fexample\u002Fmyapp\u002F\n│       │   └── MainActivity.kt\n│       └── res\u002F\n│           ├── values\u002F\n│           │   ├── strings.xml\n│           │   ├── colors.xml\n│           │   └── themes.xml\n│           └── mipmap-*\u002F       # App icons\n",[271],{"type":53,"tag":137,"props":272,"children":274},{"__ignoreMap":273},"",[275],{"type":59,"value":269},{"type":53,"tag":277,"props":278,"children":279},"hr",{},[],{"type":53,"tag":54,"props":281,"children":283},{"id":282},"_2-project-configuration",[284],{"type":59,"value":285},"2. Project Configuration",{"type":53,"tag":258,"props":287,"children":289},{"id":288},"_21-gradleproperties",[290],{"type":59,"value":291},"2.1 gradle.properties",{"type":53,"tag":265,"props":293,"children":297},{"className":294,"code":295,"language":296,"meta":273,"style":273},"language-properties shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Required configuration\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n\n# Build optimization\norg.gradle.parallel=true\nkotlin.code.style=official\n\n# JVM memory settings (adjust based on project size)\n# Small projects: 2048m, Medium: 4096m, Large: 8192m+\n# org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8\n","properties",[298],{"type":53,"tag":137,"props":299,"children":300},{"__ignoreMap":273},[301,312,321,330,340,349,358,367,375,384,393],{"type":53,"tag":302,"props":303,"children":306},"span",{"class":304,"line":305},"line",1,[307],{"type":53,"tag":302,"props":308,"children":309},{},[310],{"type":59,"value":311},"# Required configuration\n",{"type":53,"tag":302,"props":313,"children":315},{"class":304,"line":314},2,[316],{"type":53,"tag":302,"props":317,"children":318},{},[319],{"type":59,"value":320},"android.useAndroidX=true\n",{"type":53,"tag":302,"props":322,"children":324},{"class":304,"line":323},3,[325],{"type":53,"tag":302,"props":326,"children":327},{},[328],{"type":59,"value":329},"android.enableJetifier=true\n",{"type":53,"tag":302,"props":331,"children":333},{"class":304,"line":332},4,[334],{"type":53,"tag":302,"props":335,"children":337},{"emptyLinePlaceholder":336},true,[338],{"type":59,"value":339},"\n",{"type":53,"tag":302,"props":341,"children":343},{"class":304,"line":342},5,[344],{"type":53,"tag":302,"props":345,"children":346},{},[347],{"type":59,"value":348},"# Build optimization\n",{"type":53,"tag":302,"props":350,"children":352},{"class":304,"line":351},6,[353],{"type":53,"tag":302,"props":354,"children":355},{},[356],{"type":59,"value":357},"org.gradle.parallel=true\n",{"type":53,"tag":302,"props":359,"children":361},{"class":304,"line":360},7,[362],{"type":53,"tag":302,"props":363,"children":364},{},[365],{"type":59,"value":366},"kotlin.code.style=official\n",{"type":53,"tag":302,"props":368,"children":370},{"class":304,"line":369},8,[371],{"type":53,"tag":302,"props":372,"children":373},{"emptyLinePlaceholder":336},[374],{"type":59,"value":339},{"type":53,"tag":302,"props":376,"children":378},{"class":304,"line":377},9,[379],{"type":53,"tag":302,"props":380,"children":381},{},[382],{"type":59,"value":383},"# JVM memory settings (adjust based on project size)\n",{"type":53,"tag":302,"props":385,"children":387},{"class":304,"line":386},10,[388],{"type":53,"tag":302,"props":389,"children":390},{},[391],{"type":59,"value":392},"# Small projects: 2048m, Medium: 4096m, Large: 8192m+\n",{"type":53,"tag":302,"props":394,"children":396},{"class":304,"line":395},11,[397],{"type":53,"tag":302,"props":398,"children":399},{},[400],{"type":59,"value":401},"# org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8\n",{"type":53,"tag":403,"props":404,"children":405},"blockquote",{},[406],{"type":53,"tag":62,"props":407,"children":408},{},[409,414,416,422,424,430],{"type":53,"tag":107,"props":410,"children":411},{},[412],{"type":59,"value":413},"Note",{"type":59,"value":415},": If you encounter ",{"type":53,"tag":137,"props":417,"children":419},{"className":418},[],[420],{"type":59,"value":421},"OutOfMemoryError",{"type":59,"value":423}," during build, increase ",{"type":53,"tag":137,"props":425,"children":427},{"className":426},[],[428],{"type":59,"value":429},"-Xmx",{"type":59,"value":431}," value. Large projects with many dependencies may require 8GB or more.",{"type":53,"tag":258,"props":433,"children":435},{"id":434},"_22-dependency-declaration-standards",[436],{"type":59,"value":437},"2.2 Dependency Declaration Standards",{"type":53,"tag":265,"props":439,"children":442},{"className":440,"code":441,"language":15,"meta":273,"style":273},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dependencies {\n    \u002F\u002F Use BOM to manage Compose versions\n    implementation(platform(\"androidx.compose:compose-bom:2024.02.00\"))\n    implementation(\"androidx.compose.ui:ui\")\n    implementation(\"androidx.compose.material3:material3\")\n    \n    \u002F\u002F Activity & ViewModel\n    implementation(\"androidx.activity:activity-compose:1.8.2\")\n    implementation(\"androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0\")\n}\n",[443],{"type":53,"tag":137,"props":444,"children":445},{"__ignoreMap":273},[446,454,462,470,478,486,494,502,510,518],{"type":53,"tag":302,"props":447,"children":448},{"class":304,"line":305},[449],{"type":53,"tag":302,"props":450,"children":451},{},[452],{"type":59,"value":453},"dependencies {\n",{"type":53,"tag":302,"props":455,"children":456},{"class":304,"line":314},[457],{"type":53,"tag":302,"props":458,"children":459},{},[460],{"type":59,"value":461},"    \u002F\u002F Use BOM to manage Compose versions\n",{"type":53,"tag":302,"props":463,"children":464},{"class":304,"line":323},[465],{"type":53,"tag":302,"props":466,"children":467},{},[468],{"type":59,"value":469},"    implementation(platform(\"androidx.compose:compose-bom:2024.02.00\"))\n",{"type":53,"tag":302,"props":471,"children":472},{"class":304,"line":332},[473],{"type":53,"tag":302,"props":474,"children":475},{},[476],{"type":59,"value":477},"    implementation(\"androidx.compose.ui:ui\")\n",{"type":53,"tag":302,"props":479,"children":480},{"class":304,"line":342},[481],{"type":53,"tag":302,"props":482,"children":483},{},[484],{"type":59,"value":485},"    implementation(\"androidx.compose.material3:material3\")\n",{"type":53,"tag":302,"props":487,"children":488},{"class":304,"line":351},[489],{"type":53,"tag":302,"props":490,"children":491},{},[492],{"type":59,"value":493},"    \n",{"type":53,"tag":302,"props":495,"children":496},{"class":304,"line":360},[497],{"type":53,"tag":302,"props":498,"children":499},{},[500],{"type":59,"value":501},"    \u002F\u002F Activity & ViewModel\n",{"type":53,"tag":302,"props":503,"children":504},{"class":304,"line":369},[505],{"type":53,"tag":302,"props":506,"children":507},{},[508],{"type":59,"value":509},"    implementation(\"androidx.activity:activity-compose:1.8.2\")\n",{"type":53,"tag":302,"props":511,"children":512},{"class":304,"line":377},[513],{"type":53,"tag":302,"props":514,"children":515},{},[516],{"type":59,"value":517},"    implementation(\"androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0\")\n",{"type":53,"tag":302,"props":519,"children":520},{"class":304,"line":386},[521],{"type":53,"tag":302,"props":522,"children":523},{},[524],{"type":59,"value":525},"}\n",{"type":53,"tag":258,"props":527,"children":529},{"id":528},"_23-build-variants-product-flavors",[530],{"type":59,"value":531},"2.3 Build Variants & Product Flavors",{"type":53,"tag":62,"props":533,"children":534},{},[535],{"type":59,"value":536},"Product Flavors allow you to create different versions of your app (e.g., free\u002Fpaid, dev\u002Fstaging\u002Fprod).",{"type":53,"tag":62,"props":538,"children":539},{},[540,545],{"type":53,"tag":107,"props":541,"children":542},{},[543],{"type":59,"value":544},"Configuration in app\u002Fbuild.gradle.kts",{"type":59,"value":225},{"type":53,"tag":265,"props":547,"children":549},{"className":440,"code":548,"language":15,"meta":273,"style":273},"android {\n    \u002F\u002F Define flavor dimensions\n    flavorDimensions += \"environment\"\n    \n    productFlavors {\n        create(\"dev\") {\n            dimension = \"environment\"\n            applicationIdSuffix = \".dev\"\n            versionNameSuffix = \"-dev\"\n            \n            \u002F\u002F Different config values per flavor\n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fdev-api.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"true\")\n            \n            \u002F\u002F Different resources\n            resValue(\"string\", \"app_name\", \"MyApp Dev\")\n        }\n        \n        create(\"staging\") {\n            dimension = \"environment\"\n            applicationIdSuffix = \".staging\"\n            versionNameSuffix = \"-staging\"\n            \n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fstaging-api.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"true\")\n            resValue(\"string\", \"app_name\", \"MyApp Staging\")\n        }\n        \n        create(\"prod\") {\n            dimension = \"environment\"\n            \u002F\u002F No suffix for production\n            \n            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fapi.example.com\\\"\")\n            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"false\")\n            resValue(\"string\", \"app_name\", \"MyApp\")\n        }\n    }\n    \n    buildTypes {\n        debug {\n            isDebuggable = true\n            isMinifyEnabled = false\n        }\n        release {\n            isDebuggable = false\n            isMinifyEnabled = true\n            proguardFiles(getDefaultProguardFile(\"proguard-android-optimize.txt\"), \"proguard-rules.pro\")\n        }\n    }\n}\n",[550],{"type":53,"tag":137,"props":551,"children":552},{"__ignoreMap":273},[553,561,569,577,584,592,600,608,616,624,632,640,649,658,666,675,684,693,702,711,719,728,737,745,754,762,771,779,787,796,804,813,821,830,839,848,856,865,873,882,891,900,909,917,926,935,944,953,961,969],{"type":53,"tag":302,"props":554,"children":555},{"class":304,"line":305},[556],{"type":53,"tag":302,"props":557,"children":558},{},[559],{"type":59,"value":560},"android {\n",{"type":53,"tag":302,"props":562,"children":563},{"class":304,"line":314},[564],{"type":53,"tag":302,"props":565,"children":566},{},[567],{"type":59,"value":568},"    \u002F\u002F Define flavor dimensions\n",{"type":53,"tag":302,"props":570,"children":571},{"class":304,"line":323},[572],{"type":53,"tag":302,"props":573,"children":574},{},[575],{"type":59,"value":576},"    flavorDimensions += \"environment\"\n",{"type":53,"tag":302,"props":578,"children":579},{"class":304,"line":332},[580],{"type":53,"tag":302,"props":581,"children":582},{},[583],{"type":59,"value":493},{"type":53,"tag":302,"props":585,"children":586},{"class":304,"line":342},[587],{"type":53,"tag":302,"props":588,"children":589},{},[590],{"type":59,"value":591},"    productFlavors {\n",{"type":53,"tag":302,"props":593,"children":594},{"class":304,"line":351},[595],{"type":53,"tag":302,"props":596,"children":597},{},[598],{"type":59,"value":599},"        create(\"dev\") {\n",{"type":53,"tag":302,"props":601,"children":602},{"class":304,"line":360},[603],{"type":53,"tag":302,"props":604,"children":605},{},[606],{"type":59,"value":607},"            dimension = \"environment\"\n",{"type":53,"tag":302,"props":609,"children":610},{"class":304,"line":369},[611],{"type":53,"tag":302,"props":612,"children":613},{},[614],{"type":59,"value":615},"            applicationIdSuffix = \".dev\"\n",{"type":53,"tag":302,"props":617,"children":618},{"class":304,"line":377},[619],{"type":53,"tag":302,"props":620,"children":621},{},[622],{"type":59,"value":623},"            versionNameSuffix = \"-dev\"\n",{"type":53,"tag":302,"props":625,"children":626},{"class":304,"line":386},[627],{"type":53,"tag":302,"props":628,"children":629},{},[630],{"type":59,"value":631},"            \n",{"type":53,"tag":302,"props":633,"children":634},{"class":304,"line":395},[635],{"type":53,"tag":302,"props":636,"children":637},{},[638],{"type":59,"value":639},"            \u002F\u002F Different config values per flavor\n",{"type":53,"tag":302,"props":641,"children":643},{"class":304,"line":642},12,[644],{"type":53,"tag":302,"props":645,"children":646},{},[647],{"type":59,"value":648},"            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fdev-api.example.com\\\"\")\n",{"type":53,"tag":302,"props":650,"children":652},{"class":304,"line":651},13,[653],{"type":53,"tag":302,"props":654,"children":655},{},[656],{"type":59,"value":657},"            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"true\")\n",{"type":53,"tag":302,"props":659,"children":661},{"class":304,"line":660},14,[662],{"type":53,"tag":302,"props":663,"children":664},{},[665],{"type":59,"value":631},{"type":53,"tag":302,"props":667,"children":669},{"class":304,"line":668},15,[670],{"type":53,"tag":302,"props":671,"children":672},{},[673],{"type":59,"value":674},"            \u002F\u002F Different resources\n",{"type":53,"tag":302,"props":676,"children":678},{"class":304,"line":677},16,[679],{"type":53,"tag":302,"props":680,"children":681},{},[682],{"type":59,"value":683},"            resValue(\"string\", \"app_name\", \"MyApp Dev\")\n",{"type":53,"tag":302,"props":685,"children":687},{"class":304,"line":686},17,[688],{"type":53,"tag":302,"props":689,"children":690},{},[691],{"type":59,"value":692},"        }\n",{"type":53,"tag":302,"props":694,"children":696},{"class":304,"line":695},18,[697],{"type":53,"tag":302,"props":698,"children":699},{},[700],{"type":59,"value":701},"        \n",{"type":53,"tag":302,"props":703,"children":705},{"class":304,"line":704},19,[706],{"type":53,"tag":302,"props":707,"children":708},{},[709],{"type":59,"value":710},"        create(\"staging\") {\n",{"type":53,"tag":302,"props":712,"children":714},{"class":304,"line":713},20,[715],{"type":53,"tag":302,"props":716,"children":717},{},[718],{"type":59,"value":607},{"type":53,"tag":302,"props":720,"children":722},{"class":304,"line":721},21,[723],{"type":53,"tag":302,"props":724,"children":725},{},[726],{"type":59,"value":727},"            applicationIdSuffix = \".staging\"\n",{"type":53,"tag":302,"props":729,"children":731},{"class":304,"line":730},22,[732],{"type":53,"tag":302,"props":733,"children":734},{},[735],{"type":59,"value":736},"            versionNameSuffix = \"-staging\"\n",{"type":53,"tag":302,"props":738,"children":740},{"class":304,"line":739},23,[741],{"type":53,"tag":302,"props":742,"children":743},{},[744],{"type":59,"value":631},{"type":53,"tag":302,"props":746,"children":748},{"class":304,"line":747},24,[749],{"type":53,"tag":302,"props":750,"children":751},{},[752],{"type":59,"value":753},"            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fstaging-api.example.com\\\"\")\n",{"type":53,"tag":302,"props":755,"children":757},{"class":304,"line":756},25,[758],{"type":53,"tag":302,"props":759,"children":760},{},[761],{"type":59,"value":657},{"type":53,"tag":302,"props":763,"children":765},{"class":304,"line":764},26,[766],{"type":53,"tag":302,"props":767,"children":768},{},[769],{"type":59,"value":770},"            resValue(\"string\", \"app_name\", \"MyApp Staging\")\n",{"type":53,"tag":302,"props":772,"children":774},{"class":304,"line":773},27,[775],{"type":53,"tag":302,"props":776,"children":777},{},[778],{"type":59,"value":692},{"type":53,"tag":302,"props":780,"children":782},{"class":304,"line":781},28,[783],{"type":53,"tag":302,"props":784,"children":785},{},[786],{"type":59,"value":701},{"type":53,"tag":302,"props":788,"children":790},{"class":304,"line":789},29,[791],{"type":53,"tag":302,"props":792,"children":793},{},[794],{"type":59,"value":795},"        create(\"prod\") {\n",{"type":53,"tag":302,"props":797,"children":799},{"class":304,"line":798},30,[800],{"type":53,"tag":302,"props":801,"children":802},{},[803],{"type":59,"value":607},{"type":53,"tag":302,"props":805,"children":807},{"class":304,"line":806},31,[808],{"type":53,"tag":302,"props":809,"children":810},{},[811],{"type":59,"value":812},"            \u002F\u002F No suffix for production\n",{"type":53,"tag":302,"props":814,"children":816},{"class":304,"line":815},32,[817],{"type":53,"tag":302,"props":818,"children":819},{},[820],{"type":59,"value":631},{"type":53,"tag":302,"props":822,"children":824},{"class":304,"line":823},33,[825],{"type":53,"tag":302,"props":826,"children":827},{},[828],{"type":59,"value":829},"            buildConfigField(\"String\", \"API_BASE_URL\", \"\\\"https:\u002F\u002Fapi.example.com\\\"\")\n",{"type":53,"tag":302,"props":831,"children":833},{"class":304,"line":832},34,[834],{"type":53,"tag":302,"props":835,"children":836},{},[837],{"type":59,"value":838},"            buildConfigField(\"Boolean\", \"ENABLE_LOGGING\", \"false\")\n",{"type":53,"tag":302,"props":840,"children":842},{"class":304,"line":841},35,[843],{"type":53,"tag":302,"props":844,"children":845},{},[846],{"type":59,"value":847},"            resValue(\"string\", \"app_name\", \"MyApp\")\n",{"type":53,"tag":302,"props":849,"children":851},{"class":304,"line":850},36,[852],{"type":53,"tag":302,"props":853,"children":854},{},[855],{"type":59,"value":692},{"type":53,"tag":302,"props":857,"children":859},{"class":304,"line":858},37,[860],{"type":53,"tag":302,"props":861,"children":862},{},[863],{"type":59,"value":864},"    }\n",{"type":53,"tag":302,"props":866,"children":868},{"class":304,"line":867},38,[869],{"type":53,"tag":302,"props":870,"children":871},{},[872],{"type":59,"value":493},{"type":53,"tag":302,"props":874,"children":876},{"class":304,"line":875},39,[877],{"type":53,"tag":302,"props":878,"children":879},{},[880],{"type":59,"value":881},"    buildTypes {\n",{"type":53,"tag":302,"props":883,"children":885},{"class":304,"line":884},40,[886],{"type":53,"tag":302,"props":887,"children":888},{},[889],{"type":59,"value":890},"        debug {\n",{"type":53,"tag":302,"props":892,"children":894},{"class":304,"line":893},41,[895],{"type":53,"tag":302,"props":896,"children":897},{},[898],{"type":59,"value":899},"            isDebuggable = true\n",{"type":53,"tag":302,"props":901,"children":903},{"class":304,"line":902},42,[904],{"type":53,"tag":302,"props":905,"children":906},{},[907],{"type":59,"value":908},"            isMinifyEnabled = false\n",{"type":53,"tag":302,"props":910,"children":912},{"class":304,"line":911},43,[913],{"type":53,"tag":302,"props":914,"children":915},{},[916],{"type":59,"value":692},{"type":53,"tag":302,"props":918,"children":920},{"class":304,"line":919},44,[921],{"type":53,"tag":302,"props":922,"children":923},{},[924],{"type":59,"value":925},"        release {\n",{"type":53,"tag":302,"props":927,"children":929},{"class":304,"line":928},45,[930],{"type":53,"tag":302,"props":931,"children":932},{},[933],{"type":59,"value":934},"            isDebuggable = false\n",{"type":53,"tag":302,"props":936,"children":938},{"class":304,"line":937},46,[939],{"type":53,"tag":302,"props":940,"children":941},{},[942],{"type":59,"value":943},"            isMinifyEnabled = true\n",{"type":53,"tag":302,"props":945,"children":947},{"class":304,"line":946},47,[948],{"type":53,"tag":302,"props":949,"children":950},{},[951],{"type":59,"value":952},"            proguardFiles(getDefaultProguardFile(\"proguard-android-optimize.txt\"), \"proguard-rules.pro\")\n",{"type":53,"tag":302,"props":954,"children":956},{"class":304,"line":955},48,[957],{"type":53,"tag":302,"props":958,"children":959},{},[960],{"type":59,"value":692},{"type":53,"tag":302,"props":962,"children":964},{"class":304,"line":963},49,[965],{"type":53,"tag":302,"props":966,"children":967},{},[968],{"type":59,"value":864},{"type":53,"tag":302,"props":970,"children":972},{"class":304,"line":971},50,[973],{"type":53,"tag":302,"props":974,"children":975},{},[976],{"type":59,"value":525},{"type":53,"tag":62,"props":978,"children":979},{},[980,985,987,993,995,1001,1003],{"type":53,"tag":107,"props":981,"children":982},{},[983],{"type":59,"value":984},"Build Variant Naming",{"type":59,"value":986},": ",{"type":53,"tag":137,"props":988,"children":990},{"className":989},[],[991],{"type":59,"value":992},"{flavor}{BuildType}",{"type":59,"value":994}," → e.g., ",{"type":53,"tag":137,"props":996,"children":998},{"className":997},[],[999],{"type":59,"value":1000},"devDebug",{"type":59,"value":1002},", ",{"type":53,"tag":137,"props":1004,"children":1006},{"className":1005},[],[1007],{"type":59,"value":1008},"prodRelease",{"type":53,"tag":62,"props":1010,"children":1011},{},[1012,1017],{"type":53,"tag":107,"props":1013,"children":1014},{},[1015],{"type":59,"value":1016},"Gradle Build Commands",{"type":59,"value":225},{"type":53,"tag":265,"props":1019,"children":1023},{"className":1020,"code":1021,"language":1022,"meta":273,"style":273},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# List all available build variants\n.\u002Fgradlew tasks --group=\"build\"\n\n# Build specific variant (flavor + buildType)\n.\u002Fgradlew assembleDevDebug        # Dev flavor, Debug build\n.\u002Fgradlew assembleStagingDebug    # Staging flavor, Debug build\n.\u002Fgradlew assembleProdRelease     # Prod flavor, Release build\n\n# Build all variants of a specific flavor\n.\u002Fgradlew assembleDev             # All Dev variants (debug + release)\n.\u002Fgradlew assembleProd            # All Prod variants\n\n# Build all variants of a specific build type\n.\u002Fgradlew assembleDebug           # All flavors, Debug build\n.\u002Fgradlew assembleRelease         # All flavors, Release build\n\n# Install specific variant to device\n.\u002Fgradlew installDevDebug\n.\u002Fgradlew installProdRelease\n\n# Build and install in one command\n.\u002Fgradlew installDevDebug && adb shell am start -n com.example.myapp.dev\u002F.MainActivity\n","bash",[1024],{"type":53,"tag":137,"props":1025,"children":1026},{"__ignoreMap":273},[1027,1036,1071,1078,1086,1103,1120,1137,1144,1152,1169,1186,1193,1201,1218,1235,1242,1250,1262,1274,1281,1289],{"type":53,"tag":302,"props":1028,"children":1029},{"class":304,"line":305},[1030],{"type":53,"tag":302,"props":1031,"children":1033},{"style":1032},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[1034],{"type":59,"value":1035},"# List all available build variants\n",{"type":53,"tag":302,"props":1037,"children":1038},{"class":304,"line":314},[1039,1044,1050,1055,1061,1066],{"type":53,"tag":302,"props":1040,"children":1042},{"style":1041},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1043],{"type":59,"value":163},{"type":53,"tag":302,"props":1045,"children":1047},{"style":1046},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1048],{"type":59,"value":1049}," tasks",{"type":53,"tag":302,"props":1051,"children":1052},{"style":1046},[1053],{"type":59,"value":1054}," --group=",{"type":53,"tag":302,"props":1056,"children":1058},{"style":1057},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1059],{"type":59,"value":1060},"\"",{"type":53,"tag":302,"props":1062,"children":1063},{"style":1046},[1064],{"type":59,"value":1065},"build",{"type":53,"tag":302,"props":1067,"children":1068},{"style":1057},[1069],{"type":59,"value":1070},"\"\n",{"type":53,"tag":302,"props":1072,"children":1073},{"class":304,"line":323},[1074],{"type":53,"tag":302,"props":1075,"children":1076},{"emptyLinePlaceholder":336},[1077],{"type":59,"value":339},{"type":53,"tag":302,"props":1079,"children":1080},{"class":304,"line":332},[1081],{"type":53,"tag":302,"props":1082,"children":1083},{"style":1032},[1084],{"type":59,"value":1085},"# Build specific variant (flavor + buildType)\n",{"type":53,"tag":302,"props":1087,"children":1088},{"class":304,"line":342},[1089,1093,1098],{"type":53,"tag":302,"props":1090,"children":1091},{"style":1041},[1092],{"type":59,"value":163},{"type":53,"tag":302,"props":1094,"children":1095},{"style":1046},[1096],{"type":59,"value":1097}," assembleDevDebug",{"type":53,"tag":302,"props":1099,"children":1100},{"style":1032},[1101],{"type":59,"value":1102},"        # Dev flavor, Debug build\n",{"type":53,"tag":302,"props":1104,"children":1105},{"class":304,"line":351},[1106,1110,1115],{"type":53,"tag":302,"props":1107,"children":1108},{"style":1041},[1109],{"type":59,"value":163},{"type":53,"tag":302,"props":1111,"children":1112},{"style":1046},[1113],{"type":59,"value":1114}," assembleStagingDebug",{"type":53,"tag":302,"props":1116,"children":1117},{"style":1032},[1118],{"type":59,"value":1119},"    # Staging flavor, Debug build\n",{"type":53,"tag":302,"props":1121,"children":1122},{"class":304,"line":360},[1123,1127,1132],{"type":53,"tag":302,"props":1124,"children":1125},{"style":1041},[1126],{"type":59,"value":163},{"type":53,"tag":302,"props":1128,"children":1129},{"style":1046},[1130],{"type":59,"value":1131}," assembleProdRelease",{"type":53,"tag":302,"props":1133,"children":1134},{"style":1032},[1135],{"type":59,"value":1136},"     # Prod flavor, Release build\n",{"type":53,"tag":302,"props":1138,"children":1139},{"class":304,"line":369},[1140],{"type":53,"tag":302,"props":1141,"children":1142},{"emptyLinePlaceholder":336},[1143],{"type":59,"value":339},{"type":53,"tag":302,"props":1145,"children":1146},{"class":304,"line":377},[1147],{"type":53,"tag":302,"props":1148,"children":1149},{"style":1032},[1150],{"type":59,"value":1151},"# Build all variants of a specific flavor\n",{"type":53,"tag":302,"props":1153,"children":1154},{"class":304,"line":386},[1155,1159,1164],{"type":53,"tag":302,"props":1156,"children":1157},{"style":1041},[1158],{"type":59,"value":163},{"type":53,"tag":302,"props":1160,"children":1161},{"style":1046},[1162],{"type":59,"value":1163}," assembleDev",{"type":53,"tag":302,"props":1165,"children":1166},{"style":1032},[1167],{"type":59,"value":1168},"             # All Dev variants (debug + release)\n",{"type":53,"tag":302,"props":1170,"children":1171},{"class":304,"line":395},[1172,1176,1181],{"type":53,"tag":302,"props":1173,"children":1174},{"style":1041},[1175],{"type":59,"value":163},{"type":53,"tag":302,"props":1177,"children":1178},{"style":1046},[1179],{"type":59,"value":1180}," assembleProd",{"type":53,"tag":302,"props":1182,"children":1183},{"style":1032},[1184],{"type":59,"value":1185},"            # All Prod variants\n",{"type":53,"tag":302,"props":1187,"children":1188},{"class":304,"line":642},[1189],{"type":53,"tag":302,"props":1190,"children":1191},{"emptyLinePlaceholder":336},[1192],{"type":59,"value":339},{"type":53,"tag":302,"props":1194,"children":1195},{"class":304,"line":651},[1196],{"type":53,"tag":302,"props":1197,"children":1198},{"style":1032},[1199],{"type":59,"value":1200},"# Build all variants of a specific build type\n",{"type":53,"tag":302,"props":1202,"children":1203},{"class":304,"line":660},[1204,1208,1213],{"type":53,"tag":302,"props":1205,"children":1206},{"style":1041},[1207],{"type":59,"value":163},{"type":53,"tag":302,"props":1209,"children":1210},{"style":1046},[1211],{"type":59,"value":1212}," assembleDebug",{"type":53,"tag":302,"props":1214,"children":1215},{"style":1032},[1216],{"type":59,"value":1217},"           # All flavors, Debug build\n",{"type":53,"tag":302,"props":1219,"children":1220},{"class":304,"line":668},[1221,1225,1230],{"type":53,"tag":302,"props":1222,"children":1223},{"style":1041},[1224],{"type":59,"value":163},{"type":53,"tag":302,"props":1226,"children":1227},{"style":1046},[1228],{"type":59,"value":1229}," assembleRelease",{"type":53,"tag":302,"props":1231,"children":1232},{"style":1032},[1233],{"type":59,"value":1234},"         # All flavors, Release build\n",{"type":53,"tag":302,"props":1236,"children":1237},{"class":304,"line":677},[1238],{"type":53,"tag":302,"props":1239,"children":1240},{"emptyLinePlaceholder":336},[1241],{"type":59,"value":339},{"type":53,"tag":302,"props":1243,"children":1244},{"class":304,"line":686},[1245],{"type":53,"tag":302,"props":1246,"children":1247},{"style":1032},[1248],{"type":59,"value":1249},"# Install specific variant to device\n",{"type":53,"tag":302,"props":1251,"children":1252},{"class":304,"line":695},[1253,1257],{"type":53,"tag":302,"props":1254,"children":1255},{"style":1041},[1256],{"type":59,"value":163},{"type":53,"tag":302,"props":1258,"children":1259},{"style":1046},[1260],{"type":59,"value":1261}," installDevDebug\n",{"type":53,"tag":302,"props":1263,"children":1264},{"class":304,"line":704},[1265,1269],{"type":53,"tag":302,"props":1266,"children":1267},{"style":1041},[1268],{"type":59,"value":163},{"type":53,"tag":302,"props":1270,"children":1271},{"style":1046},[1272],{"type":59,"value":1273}," installProdRelease\n",{"type":53,"tag":302,"props":1275,"children":1276},{"class":304,"line":713},[1277],{"type":53,"tag":302,"props":1278,"children":1279},{"emptyLinePlaceholder":336},[1280],{"type":59,"value":339},{"type":53,"tag":302,"props":1282,"children":1283},{"class":304,"line":721},[1284],{"type":53,"tag":302,"props":1285,"children":1286},{"style":1032},[1287],{"type":59,"value":1288},"# Build and install in one command\n",{"type":53,"tag":302,"props":1290,"children":1291},{"class":304,"line":730},[1292,1296,1301,1306,1311,1316,1321,1326,1331],{"type":53,"tag":302,"props":1293,"children":1294},{"style":1041},[1295],{"type":59,"value":163},{"type":53,"tag":302,"props":1297,"children":1298},{"style":1046},[1299],{"type":59,"value":1300}," installDevDebug",{"type":53,"tag":302,"props":1302,"children":1303},{"style":1057},[1304],{"type":59,"value":1305}," &&",{"type":53,"tag":302,"props":1307,"children":1308},{"style":1041},[1309],{"type":59,"value":1310}," adb",{"type":53,"tag":302,"props":1312,"children":1313},{"style":1046},[1314],{"type":59,"value":1315}," shell",{"type":53,"tag":302,"props":1317,"children":1318},{"style":1046},[1319],{"type":59,"value":1320}," am",{"type":53,"tag":302,"props":1322,"children":1323},{"style":1046},[1324],{"type":59,"value":1325}," start",{"type":53,"tag":302,"props":1327,"children":1328},{"style":1046},[1329],{"type":59,"value":1330}," -n",{"type":53,"tag":302,"props":1332,"children":1333},{"style":1046},[1334],{"type":59,"value":1335}," com.example.myapp.dev\u002F.MainActivity\n",{"type":53,"tag":62,"props":1337,"children":1338},{},[1339,1344],{"type":53,"tag":107,"props":1340,"children":1341},{},[1342],{"type":59,"value":1343},"Access BuildConfig in Code",{"type":59,"value":225},{"type":53,"tag":403,"props":1346,"children":1347},{},[1348,1372],{"type":53,"tag":62,"props":1349,"children":1350},{},[1351,1355,1357,1363,1365,1371],{"type":53,"tag":107,"props":1352,"children":1353},{},[1354],{"type":59,"value":413},{"type":59,"value":1356},": Starting from AGP 8.0, ",{"type":53,"tag":137,"props":1358,"children":1360},{"className":1359},[],[1361],{"type":59,"value":1362},"BuildConfig",{"type":59,"value":1364}," is no longer generated by default. You must explicitly enable it in your ",{"type":53,"tag":137,"props":1366,"children":1368},{"className":1367},[],[1369],{"type":59,"value":1370},"build.gradle.kts",{"type":59,"value":225},{"type":53,"tag":265,"props":1373,"children":1375},{"className":440,"code":1374,"language":15,"meta":273,"style":273},"android {\n    buildFeatures {\n        buildConfig = true\n    }\n}\n",[1376],{"type":53,"tag":137,"props":1377,"children":1378},{"__ignoreMap":273},[1379,1386,1394,1402,1409],{"type":53,"tag":302,"props":1380,"children":1381},{"class":304,"line":305},[1382],{"type":53,"tag":302,"props":1383,"children":1384},{},[1385],{"type":59,"value":560},{"type":53,"tag":302,"props":1387,"children":1388},{"class":304,"line":314},[1389],{"type":53,"tag":302,"props":1390,"children":1391},{},[1392],{"type":59,"value":1393},"    buildFeatures {\n",{"type":53,"tag":302,"props":1395,"children":1396},{"class":304,"line":323},[1397],{"type":53,"tag":302,"props":1398,"children":1399},{},[1400],{"type":59,"value":1401},"        buildConfig = true\n",{"type":53,"tag":302,"props":1403,"children":1404},{"class":304,"line":332},[1405],{"type":53,"tag":302,"props":1406,"children":1407},{},[1408],{"type":59,"value":864},{"type":53,"tag":302,"props":1410,"children":1411},{"class":304,"line":342},[1412],{"type":53,"tag":302,"props":1413,"children":1414},{},[1415],{"type":59,"value":525},{"type":53,"tag":265,"props":1417,"children":1419},{"className":440,"code":1418,"language":15,"meta":273,"style":273},"\u002F\u002F Use build config values in your code\nval apiUrl = BuildConfig.API_BASE_URL\nval isLoggingEnabled = BuildConfig.ENABLE_LOGGING\n\nif (BuildConfig.DEBUG) {\n    \u002F\u002F Debug-only code\n}\n",[1420],{"type":53,"tag":137,"props":1421,"children":1422},{"__ignoreMap":273},[1423,1431,1439,1447,1454,1462,1470],{"type":53,"tag":302,"props":1424,"children":1425},{"class":304,"line":305},[1426],{"type":53,"tag":302,"props":1427,"children":1428},{},[1429],{"type":59,"value":1430},"\u002F\u002F Use build config values in your code\n",{"type":53,"tag":302,"props":1432,"children":1433},{"class":304,"line":314},[1434],{"type":53,"tag":302,"props":1435,"children":1436},{},[1437],{"type":59,"value":1438},"val apiUrl = BuildConfig.API_BASE_URL\n",{"type":53,"tag":302,"props":1440,"children":1441},{"class":304,"line":323},[1442],{"type":53,"tag":302,"props":1443,"children":1444},{},[1445],{"type":59,"value":1446},"val isLoggingEnabled = BuildConfig.ENABLE_LOGGING\n",{"type":53,"tag":302,"props":1448,"children":1449},{"class":304,"line":332},[1450],{"type":53,"tag":302,"props":1451,"children":1452},{"emptyLinePlaceholder":336},[1453],{"type":59,"value":339},{"type":53,"tag":302,"props":1455,"children":1456},{"class":304,"line":342},[1457],{"type":53,"tag":302,"props":1458,"children":1459},{},[1460],{"type":59,"value":1461},"if (BuildConfig.DEBUG) {\n",{"type":53,"tag":302,"props":1463,"children":1464},{"class":304,"line":351},[1465],{"type":53,"tag":302,"props":1466,"children":1467},{},[1468],{"type":59,"value":1469},"    \u002F\u002F Debug-only code\n",{"type":53,"tag":302,"props":1471,"children":1472},{"class":304,"line":360},[1473],{"type":53,"tag":302,"props":1474,"children":1475},{},[1476],{"type":59,"value":525},{"type":53,"tag":62,"props":1478,"children":1479},{},[1480,1485],{"type":53,"tag":107,"props":1481,"children":1482},{},[1483],{"type":59,"value":1484},"Flavor-Specific Source Sets",{"type":59,"value":225},{"type":53,"tag":265,"props":1487,"children":1490},{"className":1488,"code":1489,"language":59},[268],"app\u002Fsrc\u002F\n├── main\u002F           # Shared code for all flavors\n├── dev\u002F            # Dev-only code and resources\n│   ├── java\u002F\n│   └── res\u002F\n├── staging\u002F        # Staging-only code and resources\n├── prod\u002F           # Prod-only code and resources\n├── debug\u002F          # Debug build type code\n└── release\u002F        # Release build type code\n",[1491],{"type":53,"tag":137,"props":1492,"children":1493},{"__ignoreMap":273},[1494],{"type":59,"value":1489},{"type":53,"tag":62,"props":1496,"children":1497},{},[1498,1503],{"type":53,"tag":107,"props":1499,"children":1500},{},[1501],{"type":59,"value":1502},"Multiple Flavor Dimensions",{"type":59,"value":1504}," (e.g., environment + tier):",{"type":53,"tag":265,"props":1506,"children":1508},{"className":440,"code":1507,"language":15,"meta":273,"style":273},"android {\n    flavorDimensions += listOf(\"environment\", \"tier\")\n    \n    productFlavors {\n        create(\"dev\") { dimension = \"environment\" }\n        create(\"prod\") { dimension = \"environment\" }\n        \n        create(\"free\") { dimension = \"tier\" }\n        create(\"paid\") { dimension = \"tier\" }\n    }\n}\n\u002F\u002F Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc.\n",[1509],{"type":53,"tag":137,"props":1510,"children":1511},{"__ignoreMap":273},[1512,1519,1527,1534,1541,1549,1557,1564,1572,1580,1587,1594],{"type":53,"tag":302,"props":1513,"children":1514},{"class":304,"line":305},[1515],{"type":53,"tag":302,"props":1516,"children":1517},{},[1518],{"type":59,"value":560},{"type":53,"tag":302,"props":1520,"children":1521},{"class":304,"line":314},[1522],{"type":53,"tag":302,"props":1523,"children":1524},{},[1525],{"type":59,"value":1526},"    flavorDimensions += listOf(\"environment\", \"tier\")\n",{"type":53,"tag":302,"props":1528,"children":1529},{"class":304,"line":323},[1530],{"type":53,"tag":302,"props":1531,"children":1532},{},[1533],{"type":59,"value":493},{"type":53,"tag":302,"props":1535,"children":1536},{"class":304,"line":332},[1537],{"type":53,"tag":302,"props":1538,"children":1539},{},[1540],{"type":59,"value":591},{"type":53,"tag":302,"props":1542,"children":1543},{"class":304,"line":342},[1544],{"type":53,"tag":302,"props":1545,"children":1546},{},[1547],{"type":59,"value":1548},"        create(\"dev\") { dimension = \"environment\" }\n",{"type":53,"tag":302,"props":1550,"children":1551},{"class":304,"line":351},[1552],{"type":53,"tag":302,"props":1553,"children":1554},{},[1555],{"type":59,"value":1556},"        create(\"prod\") { dimension = \"environment\" }\n",{"type":53,"tag":302,"props":1558,"children":1559},{"class":304,"line":360},[1560],{"type":53,"tag":302,"props":1561,"children":1562},{},[1563],{"type":59,"value":701},{"type":53,"tag":302,"props":1565,"children":1566},{"class":304,"line":369},[1567],{"type":53,"tag":302,"props":1568,"children":1569},{},[1570],{"type":59,"value":1571},"        create(\"free\") { dimension = \"tier\" }\n",{"type":53,"tag":302,"props":1573,"children":1574},{"class":304,"line":377},[1575],{"type":53,"tag":302,"props":1576,"children":1577},{},[1578],{"type":59,"value":1579},"        create(\"paid\") { dimension = \"tier\" }\n",{"type":53,"tag":302,"props":1581,"children":1582},{"class":304,"line":386},[1583],{"type":53,"tag":302,"props":1584,"children":1585},{},[1586],{"type":59,"value":864},{"type":53,"tag":302,"props":1588,"children":1589},{"class":304,"line":395},[1590],{"type":53,"tag":302,"props":1591,"children":1592},{},[1593],{"type":59,"value":525},{"type":53,"tag":302,"props":1595,"children":1596},{"class":304,"line":642},[1597],{"type":53,"tag":302,"props":1598,"children":1599},{},[1600],{"type":59,"value":1601},"\u002F\u002F Results in: devFreeDebug, devPaidDebug, prodFreeRelease, etc.\n",{"type":53,"tag":277,"props":1603,"children":1604},{},[],{"type":53,"tag":54,"props":1606,"children":1608},{"id":1607},"_3-kotlin-development-standards",[1609],{"type":59,"value":1610},"3. Kotlin Development Standards",{"type":53,"tag":258,"props":1612,"children":1614},{"id":1613},"_31-naming-conventions",[1615],{"type":59,"value":1616},"3.1 Naming Conventions",{"type":53,"tag":68,"props":1618,"children":1619},{},[1620,1641],{"type":53,"tag":72,"props":1621,"children":1622},{},[1623],{"type":53,"tag":76,"props":1624,"children":1625},{},[1626,1631,1636],{"type":53,"tag":80,"props":1627,"children":1628},{},[1629],{"type":59,"value":1630},"Type",{"type":53,"tag":80,"props":1632,"children":1633},{},[1634],{"type":59,"value":1635},"Convention",{"type":53,"tag":80,"props":1637,"children":1638},{},[1639],{"type":59,"value":1640},"Example",{"type":53,"tag":96,"props":1642,"children":1643},{},[1644,1673,1702,1724,1746],{"type":53,"tag":76,"props":1645,"children":1646},{},[1647,1652,1657],{"type":53,"tag":103,"props":1648,"children":1649},{},[1650],{"type":59,"value":1651},"Class\u002FInterface",{"type":53,"tag":103,"props":1653,"children":1654},{},[1655],{"type":59,"value":1656},"PascalCase",{"type":53,"tag":103,"props":1658,"children":1659},{},[1660,1666,1667],{"type":53,"tag":137,"props":1661,"children":1663},{"className":1662},[],[1664],{"type":59,"value":1665},"UserRepository",{"type":59,"value":1002},{"type":53,"tag":137,"props":1668,"children":1670},{"className":1669},[],[1671],{"type":59,"value":1672},"MainActivity",{"type":53,"tag":76,"props":1674,"children":1675},{},[1676,1681,1686],{"type":53,"tag":103,"props":1677,"children":1678},{},[1679],{"type":59,"value":1680},"Function\u002FVariable",{"type":53,"tag":103,"props":1682,"children":1683},{},[1684],{"type":59,"value":1685},"camelCase",{"type":53,"tag":103,"props":1687,"children":1688},{},[1689,1695,1696],{"type":53,"tag":137,"props":1690,"children":1692},{"className":1691},[],[1693],{"type":59,"value":1694},"getUserName()",{"type":59,"value":1002},{"type":53,"tag":137,"props":1697,"children":1699},{"className":1698},[],[1700],{"type":59,"value":1701},"isLoading",{"type":53,"tag":76,"props":1703,"children":1704},{},[1705,1710,1715],{"type":53,"tag":103,"props":1706,"children":1707},{},[1708],{"type":59,"value":1709},"Constant",{"type":53,"tag":103,"props":1711,"children":1712},{},[1713],{"type":59,"value":1714},"SCREAMING_SNAKE",{"type":53,"tag":103,"props":1716,"children":1717},{},[1718],{"type":53,"tag":137,"props":1719,"children":1721},{"className":1720},[],[1722],{"type":59,"value":1723},"MAX_RETRY_COUNT",{"type":53,"tag":76,"props":1725,"children":1726},{},[1727,1732,1737],{"type":53,"tag":103,"props":1728,"children":1729},{},[1730],{"type":59,"value":1731},"Package",{"type":53,"tag":103,"props":1733,"children":1734},{},[1735],{"type":59,"value":1736},"lowercase",{"type":53,"tag":103,"props":1738,"children":1739},{},[1740],{"type":53,"tag":137,"props":1741,"children":1743},{"className":1742},[],[1744],{"type":59,"value":1745},"com.example.myapp",{"type":53,"tag":76,"props":1747,"children":1748},{},[1749,1754,1758],{"type":53,"tag":103,"props":1750,"children":1751},{},[1752],{"type":59,"value":1753},"Composable",{"type":53,"tag":103,"props":1755,"children":1756},{},[1757],{"type":59,"value":1656},{"type":53,"tag":103,"props":1759,"children":1760},{},[1761],{"type":53,"tag":137,"props":1762,"children":1764},{"className":1763},[],[1765],{"type":59,"value":1766},"@Composable fun UserCard()",{"type":53,"tag":258,"props":1768,"children":1770},{"id":1769},"_32-code-standards-important",[1771],{"type":59,"value":1772},"3.2 Code Standards (Important)",{"type":53,"tag":62,"props":1774,"children":1775},{},[1776,1781],{"type":53,"tag":107,"props":1777,"children":1778},{},[1779],{"type":59,"value":1780},"Null Safety",{"type":59,"value":225},{"type":53,"tag":265,"props":1783,"children":1785},{"className":440,"code":1784,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Avoid: Non-null assertion !! (may crash)\nval name = user!!.name\n\n\u002F\u002F ✅ Recommended: Safe call + default value\nval name = user?.name ?: \"Unknown\"\n\n\u002F\u002F ✅ Recommended: let handling\nuser?.let { processUser(it) }\n",[1786],{"type":53,"tag":137,"props":1787,"children":1788},{"__ignoreMap":273},[1789,1797,1805,1812,1820,1828,1835,1843],{"type":53,"tag":302,"props":1790,"children":1791},{"class":304,"line":305},[1792],{"type":53,"tag":302,"props":1793,"children":1794},{},[1795],{"type":59,"value":1796},"\u002F\u002F ❌ Avoid: Non-null assertion !! (may crash)\n",{"type":53,"tag":302,"props":1798,"children":1799},{"class":304,"line":314},[1800],{"type":53,"tag":302,"props":1801,"children":1802},{},[1803],{"type":59,"value":1804},"val name = user!!.name\n",{"type":53,"tag":302,"props":1806,"children":1807},{"class":304,"line":323},[1808],{"type":53,"tag":302,"props":1809,"children":1810},{"emptyLinePlaceholder":336},[1811],{"type":59,"value":339},{"type":53,"tag":302,"props":1813,"children":1814},{"class":304,"line":332},[1815],{"type":53,"tag":302,"props":1816,"children":1817},{},[1818],{"type":59,"value":1819},"\u002F\u002F ✅ Recommended: Safe call + default value\n",{"type":53,"tag":302,"props":1821,"children":1822},{"class":304,"line":342},[1823],{"type":53,"tag":302,"props":1824,"children":1825},{},[1826],{"type":59,"value":1827},"val name = user?.name ?: \"Unknown\"\n",{"type":53,"tag":302,"props":1829,"children":1830},{"class":304,"line":351},[1831],{"type":53,"tag":302,"props":1832,"children":1833},{"emptyLinePlaceholder":336},[1834],{"type":59,"value":339},{"type":53,"tag":302,"props":1836,"children":1837},{"class":304,"line":360},[1838],{"type":53,"tag":302,"props":1839,"children":1840},{},[1841],{"type":59,"value":1842},"\u002F\u002F ✅ Recommended: let handling\n",{"type":53,"tag":302,"props":1844,"children":1845},{"class":304,"line":369},[1846],{"type":53,"tag":302,"props":1847,"children":1848},{},[1849],{"type":59,"value":1850},"user?.let { processUser(it) }\n",{"type":53,"tag":62,"props":1852,"children":1853},{},[1854,1859],{"type":53,"tag":107,"props":1855,"children":1856},{},[1857],{"type":59,"value":1858},"Exception Handling",{"type":59,"value":225},{"type":53,"tag":265,"props":1861,"children":1863},{"className":440,"code":1862,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Avoid: Random try-catch in business layer swallowing exceptions\nfun loadData() {\n    try {\n        val data = api.fetch()\n    } catch (e: Exception) {\n        \u002F\u002F Swallowing exception, hard to debug\n    }\n}\n\n\u002F\u002F ✅ Recommended: Let exceptions propagate, handle at appropriate layer\nsuspend fun loadData(): Result\u003CData> {\n    return try {\n        Result.success(api.fetch())\n    } catch (e: Exception) {\n        Result.failure(e)  \u002F\u002F Wrap and return, let caller decide handling\n    }\n}\n\n\u002F\u002F ✅ Recommended: Unified handling in ViewModel\nviewModelScope.launch {\n    runCatching { repository.loadData() }\n        .onSuccess { _uiState.value = UiState.Success(it) }\n        .onFailure { _uiState.value = UiState.Error(it.message) }\n}\n",[1864],{"type":53,"tag":137,"props":1865,"children":1866},{"__ignoreMap":273},[1867,1875,1883,1891,1899,1907,1915,1922,1929,1936,1944,1952,1960,1968,1975,1983,1990,1997,2004,2012,2020,2028,2036,2044],{"type":53,"tag":302,"props":1868,"children":1869},{"class":304,"line":305},[1870],{"type":53,"tag":302,"props":1871,"children":1872},{},[1873],{"type":59,"value":1874},"\u002F\u002F ❌ Avoid: Random try-catch in business layer swallowing exceptions\n",{"type":53,"tag":302,"props":1876,"children":1877},{"class":304,"line":314},[1878],{"type":53,"tag":302,"props":1879,"children":1880},{},[1881],{"type":59,"value":1882},"fun loadData() {\n",{"type":53,"tag":302,"props":1884,"children":1885},{"class":304,"line":323},[1886],{"type":53,"tag":302,"props":1887,"children":1888},{},[1889],{"type":59,"value":1890},"    try {\n",{"type":53,"tag":302,"props":1892,"children":1893},{"class":304,"line":332},[1894],{"type":53,"tag":302,"props":1895,"children":1896},{},[1897],{"type":59,"value":1898},"        val data = api.fetch()\n",{"type":53,"tag":302,"props":1900,"children":1901},{"class":304,"line":342},[1902],{"type":53,"tag":302,"props":1903,"children":1904},{},[1905],{"type":59,"value":1906},"    } catch (e: Exception) {\n",{"type":53,"tag":302,"props":1908,"children":1909},{"class":304,"line":351},[1910],{"type":53,"tag":302,"props":1911,"children":1912},{},[1913],{"type":59,"value":1914},"        \u002F\u002F Swallowing exception, hard to debug\n",{"type":53,"tag":302,"props":1916,"children":1917},{"class":304,"line":360},[1918],{"type":53,"tag":302,"props":1919,"children":1920},{},[1921],{"type":59,"value":864},{"type":53,"tag":302,"props":1923,"children":1924},{"class":304,"line":369},[1925],{"type":53,"tag":302,"props":1926,"children":1927},{},[1928],{"type":59,"value":525},{"type":53,"tag":302,"props":1930,"children":1931},{"class":304,"line":377},[1932],{"type":53,"tag":302,"props":1933,"children":1934},{"emptyLinePlaceholder":336},[1935],{"type":59,"value":339},{"type":53,"tag":302,"props":1937,"children":1938},{"class":304,"line":386},[1939],{"type":53,"tag":302,"props":1940,"children":1941},{},[1942],{"type":59,"value":1943},"\u002F\u002F ✅ Recommended: Let exceptions propagate, handle at appropriate layer\n",{"type":53,"tag":302,"props":1945,"children":1946},{"class":304,"line":395},[1947],{"type":53,"tag":302,"props":1948,"children":1949},{},[1950],{"type":59,"value":1951},"suspend fun loadData(): Result\u003CData> {\n",{"type":53,"tag":302,"props":1953,"children":1954},{"class":304,"line":642},[1955],{"type":53,"tag":302,"props":1956,"children":1957},{},[1958],{"type":59,"value":1959},"    return try {\n",{"type":53,"tag":302,"props":1961,"children":1962},{"class":304,"line":651},[1963],{"type":53,"tag":302,"props":1964,"children":1965},{},[1966],{"type":59,"value":1967},"        Result.success(api.fetch())\n",{"type":53,"tag":302,"props":1969,"children":1970},{"class":304,"line":660},[1971],{"type":53,"tag":302,"props":1972,"children":1973},{},[1974],{"type":59,"value":1906},{"type":53,"tag":302,"props":1976,"children":1977},{"class":304,"line":668},[1978],{"type":53,"tag":302,"props":1979,"children":1980},{},[1981],{"type":59,"value":1982},"        Result.failure(e)  \u002F\u002F Wrap and return, let caller decide handling\n",{"type":53,"tag":302,"props":1984,"children":1985},{"class":304,"line":677},[1986],{"type":53,"tag":302,"props":1987,"children":1988},{},[1989],{"type":59,"value":864},{"type":53,"tag":302,"props":1991,"children":1992},{"class":304,"line":686},[1993],{"type":53,"tag":302,"props":1994,"children":1995},{},[1996],{"type":59,"value":525},{"type":53,"tag":302,"props":1998,"children":1999},{"class":304,"line":695},[2000],{"type":53,"tag":302,"props":2001,"children":2002},{"emptyLinePlaceholder":336},[2003],{"type":59,"value":339},{"type":53,"tag":302,"props":2005,"children":2006},{"class":304,"line":704},[2007],{"type":53,"tag":302,"props":2008,"children":2009},{},[2010],{"type":59,"value":2011},"\u002F\u002F ✅ Recommended: Unified handling in ViewModel\n",{"type":53,"tag":302,"props":2013,"children":2014},{"class":304,"line":713},[2015],{"type":53,"tag":302,"props":2016,"children":2017},{},[2018],{"type":59,"value":2019},"viewModelScope.launch {\n",{"type":53,"tag":302,"props":2021,"children":2022},{"class":304,"line":721},[2023],{"type":53,"tag":302,"props":2024,"children":2025},{},[2026],{"type":59,"value":2027},"    runCatching { repository.loadData() }\n",{"type":53,"tag":302,"props":2029,"children":2030},{"class":304,"line":730},[2031],{"type":53,"tag":302,"props":2032,"children":2033},{},[2034],{"type":59,"value":2035},"        .onSuccess { _uiState.value = UiState.Success(it) }\n",{"type":53,"tag":302,"props":2037,"children":2038},{"class":304,"line":739},[2039],{"type":53,"tag":302,"props":2040,"children":2041},{},[2042],{"type":59,"value":2043},"        .onFailure { _uiState.value = UiState.Error(it.message) }\n",{"type":53,"tag":302,"props":2045,"children":2046},{"class":304,"line":747},[2047],{"type":53,"tag":302,"props":2048,"children":2049},{},[2050],{"type":59,"value":525},{"type":53,"tag":258,"props":2052,"children":2054},{"id":2053},"_33-threading-coroutines-critical",[2055],{"type":59,"value":2056},"3.3 Threading & Coroutines (Critical)",{"type":53,"tag":62,"props":2058,"children":2059},{},[2060,2065],{"type":53,"tag":107,"props":2061,"children":2062},{},[2063],{"type":59,"value":2064},"Thread Selection Principles",{"type":59,"value":225},{"type":53,"tag":68,"props":2067,"children":2068},{},[2069,2090],{"type":53,"tag":72,"props":2070,"children":2071},{},[2072],{"type":53,"tag":76,"props":2073,"children":2074},{},[2075,2080,2085],{"type":53,"tag":80,"props":2076,"children":2077},{},[2078],{"type":59,"value":2079},"Operation Type",{"type":53,"tag":80,"props":2081,"children":2082},{},[2083],{"type":59,"value":2084},"Thread",{"type":53,"tag":80,"props":2086,"children":2087},{},[2088],{"type":59,"value":2089},"Description",{"type":53,"tag":96,"props":2091,"children":2092},{},[2093,2115,2137,2158],{"type":53,"tag":76,"props":2094,"children":2095},{},[2096,2101,2110],{"type":53,"tag":103,"props":2097,"children":2098},{},[2099],{"type":59,"value":2100},"UI Updates",{"type":53,"tag":103,"props":2102,"children":2103},{},[2104],{"type":53,"tag":137,"props":2105,"children":2107},{"className":2106},[],[2108],{"type":59,"value":2109},"Dispatchers.Main",{"type":53,"tag":103,"props":2111,"children":2112},{},[2113],{"type":59,"value":2114},"Update View, State, LiveData",{"type":53,"tag":76,"props":2116,"children":2117},{},[2118,2123,2132],{"type":53,"tag":103,"props":2119,"children":2120},{},[2121],{"type":59,"value":2122},"Network Requests",{"type":53,"tag":103,"props":2124,"children":2125},{},[2126],{"type":53,"tag":137,"props":2127,"children":2129},{"className":2128},[],[2130],{"type":59,"value":2131},"Dispatchers.IO",{"type":53,"tag":103,"props":2133,"children":2134},{},[2135],{"type":59,"value":2136},"HTTP calls, API requests",{"type":53,"tag":76,"props":2138,"children":2139},{},[2140,2145,2153],{"type":53,"tag":103,"props":2141,"children":2142},{},[2143],{"type":59,"value":2144},"File I\u002FO",{"type":53,"tag":103,"props":2146,"children":2147},{},[2148],{"type":53,"tag":137,"props":2149,"children":2151},{"className":2150},[],[2152],{"type":59,"value":2131},{"type":53,"tag":103,"props":2154,"children":2155},{},[2156],{"type":59,"value":2157},"Local storage, database operations",{"type":53,"tag":76,"props":2159,"children":2160},{},[2161,2166,2175],{"type":53,"tag":103,"props":2162,"children":2163},{},[2164],{"type":59,"value":2165},"Compute Intensive",{"type":53,"tag":103,"props":2167,"children":2168},{},[2169],{"type":53,"tag":137,"props":2170,"children":2172},{"className":2171},[],[2173],{"type":59,"value":2174},"Dispatchers.Default",{"type":53,"tag":103,"props":2176,"children":2177},{},[2178],{"type":59,"value":2179},"JSON parsing, sorting, encryption",{"type":53,"tag":62,"props":2181,"children":2182},{},[2183,2188],{"type":53,"tag":107,"props":2184,"children":2185},{},[2186],{"type":59,"value":2187},"Correct Usage",{"type":59,"value":225},{"type":53,"tag":265,"props":2190,"children":2192},{"className":440,"code":2191,"language":15,"meta":273,"style":273},"\u002F\u002F In ViewModel\nviewModelScope.launch {\n    \u002F\u002F Default Main thread, can update UI State\n    _uiState.value = UiState.Loading\n    \n    \u002F\u002F Switch to IO thread for network request\n    val result = withContext(Dispatchers.IO) {\n        repository.fetchData()\n    }\n    \n    \u002F\u002F Automatically returns to Main thread, update UI\n    _uiState.value = UiState.Success(result)\n}\n\n\u002F\u002F In Repository (suspend functions should be main-safe)\nsuspend fun fetchData(): Data = withContext(Dispatchers.IO) {\n    api.getData()\n}\n",[2193],{"type":53,"tag":137,"props":2194,"children":2195},{"__ignoreMap":273},[2196,2204,2211,2219,2227,2234,2242,2250,2258,2265,2272,2280,2288,2295,2302,2310,2318,2326],{"type":53,"tag":302,"props":2197,"children":2198},{"class":304,"line":305},[2199],{"type":53,"tag":302,"props":2200,"children":2201},{},[2202],{"type":59,"value":2203},"\u002F\u002F In ViewModel\n",{"type":53,"tag":302,"props":2205,"children":2206},{"class":304,"line":314},[2207],{"type":53,"tag":302,"props":2208,"children":2209},{},[2210],{"type":59,"value":2019},{"type":53,"tag":302,"props":2212,"children":2213},{"class":304,"line":323},[2214],{"type":53,"tag":302,"props":2215,"children":2216},{},[2217],{"type":59,"value":2218},"    \u002F\u002F Default Main thread, can update UI State\n",{"type":53,"tag":302,"props":2220,"children":2221},{"class":304,"line":332},[2222],{"type":53,"tag":302,"props":2223,"children":2224},{},[2225],{"type":59,"value":2226},"    _uiState.value = UiState.Loading\n",{"type":53,"tag":302,"props":2228,"children":2229},{"class":304,"line":342},[2230],{"type":53,"tag":302,"props":2231,"children":2232},{},[2233],{"type":59,"value":493},{"type":53,"tag":302,"props":2235,"children":2236},{"class":304,"line":351},[2237],{"type":53,"tag":302,"props":2238,"children":2239},{},[2240],{"type":59,"value":2241},"    \u002F\u002F Switch to IO thread for network request\n",{"type":53,"tag":302,"props":2243,"children":2244},{"class":304,"line":360},[2245],{"type":53,"tag":302,"props":2246,"children":2247},{},[2248],{"type":59,"value":2249},"    val result = withContext(Dispatchers.IO) {\n",{"type":53,"tag":302,"props":2251,"children":2252},{"class":304,"line":369},[2253],{"type":53,"tag":302,"props":2254,"children":2255},{},[2256],{"type":59,"value":2257},"        repository.fetchData()\n",{"type":53,"tag":302,"props":2259,"children":2260},{"class":304,"line":377},[2261],{"type":53,"tag":302,"props":2262,"children":2263},{},[2264],{"type":59,"value":864},{"type":53,"tag":302,"props":2266,"children":2267},{"class":304,"line":386},[2268],{"type":53,"tag":302,"props":2269,"children":2270},{},[2271],{"type":59,"value":493},{"type":53,"tag":302,"props":2273,"children":2274},{"class":304,"line":395},[2275],{"type":53,"tag":302,"props":2276,"children":2277},{},[2278],{"type":59,"value":2279},"    \u002F\u002F Automatically returns to Main thread, update UI\n",{"type":53,"tag":302,"props":2281,"children":2282},{"class":304,"line":642},[2283],{"type":53,"tag":302,"props":2284,"children":2285},{},[2286],{"type":59,"value":2287},"    _uiState.value = UiState.Success(result)\n",{"type":53,"tag":302,"props":2289,"children":2290},{"class":304,"line":651},[2291],{"type":53,"tag":302,"props":2292,"children":2293},{},[2294],{"type":59,"value":525},{"type":53,"tag":302,"props":2296,"children":2297},{"class":304,"line":660},[2298],{"type":53,"tag":302,"props":2299,"children":2300},{"emptyLinePlaceholder":336},[2301],{"type":59,"value":339},{"type":53,"tag":302,"props":2303,"children":2304},{"class":304,"line":668},[2305],{"type":53,"tag":302,"props":2306,"children":2307},{},[2308],{"type":59,"value":2309},"\u002F\u002F In Repository (suspend functions should be main-safe)\n",{"type":53,"tag":302,"props":2311,"children":2312},{"class":304,"line":677},[2313],{"type":53,"tag":302,"props":2314,"children":2315},{},[2316],{"type":59,"value":2317},"suspend fun fetchData(): Data = withContext(Dispatchers.IO) {\n",{"type":53,"tag":302,"props":2319,"children":2320},{"class":304,"line":686},[2321],{"type":53,"tag":302,"props":2322,"children":2323},{},[2324],{"type":59,"value":2325},"    api.getData()\n",{"type":53,"tag":302,"props":2327,"children":2328},{"class":304,"line":695},[2329],{"type":53,"tag":302,"props":2330,"children":2331},{},[2332],{"type":59,"value":525},{"type":53,"tag":62,"props":2334,"children":2335},{},[2336,2341],{"type":53,"tag":107,"props":2337,"children":2338},{},[2339],{"type":59,"value":2340},"Common Mistakes",{"type":59,"value":225},{"type":53,"tag":265,"props":2343,"children":2345},{"className":440,"code":2344,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Updating UI on IO thread\nviewModelScope.launch(Dispatchers.IO) {\n    val data = api.fetch()\n    _uiState.value = data  \u002F\u002F Crash or warning!\n}\n\n\u002F\u002F ❌ Wrong: Executing time-consuming operation on Main thread\nviewModelScope.launch {\n    val data = api.fetch()  \u002F\u002F Blocking main thread! ANR\n}\n\n\u002F\u002F ✅ Correct: Fetch on IO, update on Main\nviewModelScope.launch {\n    val data = withContext(Dispatchers.IO) { api.fetch() }\n    _uiState.value = data\n}\n",[2346],{"type":53,"tag":137,"props":2347,"children":2348},{"__ignoreMap":273},[2349,2357,2365,2373,2381,2388,2395,2403,2410,2418,2425,2432,2440,2447,2455,2463],{"type":53,"tag":302,"props":2350,"children":2351},{"class":304,"line":305},[2352],{"type":53,"tag":302,"props":2353,"children":2354},{},[2355],{"type":59,"value":2356},"\u002F\u002F ❌ Wrong: Updating UI on IO thread\n",{"type":53,"tag":302,"props":2358,"children":2359},{"class":304,"line":314},[2360],{"type":53,"tag":302,"props":2361,"children":2362},{},[2363],{"type":59,"value":2364},"viewModelScope.launch(Dispatchers.IO) {\n",{"type":53,"tag":302,"props":2366,"children":2367},{"class":304,"line":323},[2368],{"type":53,"tag":302,"props":2369,"children":2370},{},[2371],{"type":59,"value":2372},"    val data = api.fetch()\n",{"type":53,"tag":302,"props":2374,"children":2375},{"class":304,"line":332},[2376],{"type":53,"tag":302,"props":2377,"children":2378},{},[2379],{"type":59,"value":2380},"    _uiState.value = data  \u002F\u002F Crash or warning!\n",{"type":53,"tag":302,"props":2382,"children":2383},{"class":304,"line":342},[2384],{"type":53,"tag":302,"props":2385,"children":2386},{},[2387],{"type":59,"value":525},{"type":53,"tag":302,"props":2389,"children":2390},{"class":304,"line":351},[2391],{"type":53,"tag":302,"props":2392,"children":2393},{"emptyLinePlaceholder":336},[2394],{"type":59,"value":339},{"type":53,"tag":302,"props":2396,"children":2397},{"class":304,"line":360},[2398],{"type":53,"tag":302,"props":2399,"children":2400},{},[2401],{"type":59,"value":2402},"\u002F\u002F ❌ Wrong: Executing time-consuming operation on Main thread\n",{"type":53,"tag":302,"props":2404,"children":2405},{"class":304,"line":369},[2406],{"type":53,"tag":302,"props":2407,"children":2408},{},[2409],{"type":59,"value":2019},{"type":53,"tag":302,"props":2411,"children":2412},{"class":304,"line":377},[2413],{"type":53,"tag":302,"props":2414,"children":2415},{},[2416],{"type":59,"value":2417},"    val data = api.fetch()  \u002F\u002F Blocking main thread! ANR\n",{"type":53,"tag":302,"props":2419,"children":2420},{"class":304,"line":386},[2421],{"type":53,"tag":302,"props":2422,"children":2423},{},[2424],{"type":59,"value":525},{"type":53,"tag":302,"props":2426,"children":2427},{"class":304,"line":395},[2428],{"type":53,"tag":302,"props":2429,"children":2430},{"emptyLinePlaceholder":336},[2431],{"type":59,"value":339},{"type":53,"tag":302,"props":2433,"children":2434},{"class":304,"line":642},[2435],{"type":53,"tag":302,"props":2436,"children":2437},{},[2438],{"type":59,"value":2439},"\u002F\u002F ✅ Correct: Fetch on IO, update on Main\n",{"type":53,"tag":302,"props":2441,"children":2442},{"class":304,"line":651},[2443],{"type":53,"tag":302,"props":2444,"children":2445},{},[2446],{"type":59,"value":2019},{"type":53,"tag":302,"props":2448,"children":2449},{"class":304,"line":660},[2450],{"type":53,"tag":302,"props":2451,"children":2452},{},[2453],{"type":59,"value":2454},"    val data = withContext(Dispatchers.IO) { api.fetch() }\n",{"type":53,"tag":302,"props":2456,"children":2457},{"class":304,"line":668},[2458],{"type":53,"tag":302,"props":2459,"children":2460},{},[2461],{"type":59,"value":2462},"    _uiState.value = data\n",{"type":53,"tag":302,"props":2464,"children":2465},{"class":304,"line":677},[2466],{"type":53,"tag":302,"props":2467,"children":2468},{},[2469],{"type":59,"value":525},{"type":53,"tag":258,"props":2471,"children":2473},{"id":2472},"_34-visibility-rules",[2474],{"type":59,"value":2475},"3.4 Visibility Rules",{"type":53,"tag":265,"props":2477,"children":2479},{"className":440,"code":2478,"language":15,"meta":273,"style":273},"\u002F\u002F Default is public, declare explicitly when needed\nclass UserRepository {           \u002F\u002F public\n    private val cache = mutableMapOf\u003CString, User>()  \u002F\u002F Visible only within class\n    internal fun clearCache() {} \u002F\u002F Visible only within module\n}\n\n\u002F\u002F data class properties are public by default, be careful when used across modules\ndata class User(\n    val id: String,       \u002F\u002F public\n    val name: String\n)\n",[2480],{"type":53,"tag":137,"props":2481,"children":2482},{"__ignoreMap":273},[2483,2491,2499,2507,2515,2522,2529,2537,2545,2553,2561],{"type":53,"tag":302,"props":2484,"children":2485},{"class":304,"line":305},[2486],{"type":53,"tag":302,"props":2487,"children":2488},{},[2489],{"type":59,"value":2490},"\u002F\u002F Default is public, declare explicitly when needed\n",{"type":53,"tag":302,"props":2492,"children":2493},{"class":304,"line":314},[2494],{"type":53,"tag":302,"props":2495,"children":2496},{},[2497],{"type":59,"value":2498},"class UserRepository {           \u002F\u002F public\n",{"type":53,"tag":302,"props":2500,"children":2501},{"class":304,"line":323},[2502],{"type":53,"tag":302,"props":2503,"children":2504},{},[2505],{"type":59,"value":2506},"    private val cache = mutableMapOf\u003CString, User>()  \u002F\u002F Visible only within class\n",{"type":53,"tag":302,"props":2508,"children":2509},{"class":304,"line":332},[2510],{"type":53,"tag":302,"props":2511,"children":2512},{},[2513],{"type":59,"value":2514},"    internal fun clearCache() {} \u002F\u002F Visible only within module\n",{"type":53,"tag":302,"props":2516,"children":2517},{"class":304,"line":342},[2518],{"type":53,"tag":302,"props":2519,"children":2520},{},[2521],{"type":59,"value":525},{"type":53,"tag":302,"props":2523,"children":2524},{"class":304,"line":351},[2525],{"type":53,"tag":302,"props":2526,"children":2527},{"emptyLinePlaceholder":336},[2528],{"type":59,"value":339},{"type":53,"tag":302,"props":2530,"children":2531},{"class":304,"line":360},[2532],{"type":53,"tag":302,"props":2533,"children":2534},{},[2535],{"type":59,"value":2536},"\u002F\u002F data class properties are public by default, be careful when used across modules\n",{"type":53,"tag":302,"props":2538,"children":2539},{"class":304,"line":369},[2540],{"type":53,"tag":302,"props":2541,"children":2542},{},[2543],{"type":59,"value":2544},"data class User(\n",{"type":53,"tag":302,"props":2546,"children":2547},{"class":304,"line":377},[2548],{"type":53,"tag":302,"props":2549,"children":2550},{},[2551],{"type":59,"value":2552},"    val id: String,       \u002F\u002F public\n",{"type":53,"tag":302,"props":2554,"children":2555},{"class":304,"line":386},[2556],{"type":53,"tag":302,"props":2557,"children":2558},{},[2559],{"type":59,"value":2560},"    val name: String\n",{"type":53,"tag":302,"props":2562,"children":2563},{"class":304,"line":395},[2564],{"type":53,"tag":302,"props":2565,"children":2566},{},[2567],{"type":59,"value":2568},")\n",{"type":53,"tag":258,"props":2570,"children":2572},{"id":2571},"_35-common-syntax-pitfalls",[2573],{"type":59,"value":2574},"3.5 Common Syntax Pitfalls",{"type":53,"tag":265,"props":2576,"children":2578},{"className":440,"code":2577,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Accessing uninitialized lateinit\nclass MyViewModel : ViewModel() {\n    lateinit var data: String\n    fun process() = data.length  \u002F\u002F May crash\n}\n\n\u002F\u002F ✅ Correct: Use nullable or default value\nclass MyViewModel : ViewModel() {\n    var data: String? = null\n    fun process() = data?.length ?: 0\n}\n\n\u002F\u002F ❌ Wrong: Using return in lambda\nlist.forEach { item ->\n    if (item.isEmpty()) return  \u002F\u002F Returns from outer function!\n}\n\n\u002F\u002F ✅ Correct: Use return@forEach\nlist.forEach { item ->\n    if (item.isEmpty()) return@forEach\n}\n",[2579],{"type":53,"tag":137,"props":2580,"children":2581},{"__ignoreMap":273},[2582,2590,2598,2606,2614,2621,2628,2636,2643,2651,2659,2666,2673,2681,2689,2697,2704,2711,2719,2726,2734],{"type":53,"tag":302,"props":2583,"children":2584},{"class":304,"line":305},[2585],{"type":53,"tag":302,"props":2586,"children":2587},{},[2588],{"type":59,"value":2589},"\u002F\u002F ❌ Wrong: Accessing uninitialized lateinit\n",{"type":53,"tag":302,"props":2591,"children":2592},{"class":304,"line":314},[2593],{"type":53,"tag":302,"props":2594,"children":2595},{},[2596],{"type":59,"value":2597},"class MyViewModel : ViewModel() {\n",{"type":53,"tag":302,"props":2599,"children":2600},{"class":304,"line":323},[2601],{"type":53,"tag":302,"props":2602,"children":2603},{},[2604],{"type":59,"value":2605},"    lateinit var data: String\n",{"type":53,"tag":302,"props":2607,"children":2608},{"class":304,"line":332},[2609],{"type":53,"tag":302,"props":2610,"children":2611},{},[2612],{"type":59,"value":2613},"    fun process() = data.length  \u002F\u002F May crash\n",{"type":53,"tag":302,"props":2615,"children":2616},{"class":304,"line":342},[2617],{"type":53,"tag":302,"props":2618,"children":2619},{},[2620],{"type":59,"value":525},{"type":53,"tag":302,"props":2622,"children":2623},{"class":304,"line":351},[2624],{"type":53,"tag":302,"props":2625,"children":2626},{"emptyLinePlaceholder":336},[2627],{"type":59,"value":339},{"type":53,"tag":302,"props":2629,"children":2630},{"class":304,"line":360},[2631],{"type":53,"tag":302,"props":2632,"children":2633},{},[2634],{"type":59,"value":2635},"\u002F\u002F ✅ Correct: Use nullable or default value\n",{"type":53,"tag":302,"props":2637,"children":2638},{"class":304,"line":369},[2639],{"type":53,"tag":302,"props":2640,"children":2641},{},[2642],{"type":59,"value":2597},{"type":53,"tag":302,"props":2644,"children":2645},{"class":304,"line":377},[2646],{"type":53,"tag":302,"props":2647,"children":2648},{},[2649],{"type":59,"value":2650},"    var data: String? = null\n",{"type":53,"tag":302,"props":2652,"children":2653},{"class":304,"line":386},[2654],{"type":53,"tag":302,"props":2655,"children":2656},{},[2657],{"type":59,"value":2658},"    fun process() = data?.length ?: 0\n",{"type":53,"tag":302,"props":2660,"children":2661},{"class":304,"line":395},[2662],{"type":53,"tag":302,"props":2663,"children":2664},{},[2665],{"type":59,"value":525},{"type":53,"tag":302,"props":2667,"children":2668},{"class":304,"line":642},[2669],{"type":53,"tag":302,"props":2670,"children":2671},{"emptyLinePlaceholder":336},[2672],{"type":59,"value":339},{"type":53,"tag":302,"props":2674,"children":2675},{"class":304,"line":651},[2676],{"type":53,"tag":302,"props":2677,"children":2678},{},[2679],{"type":59,"value":2680},"\u002F\u002F ❌ Wrong: Using return in lambda\n",{"type":53,"tag":302,"props":2682,"children":2683},{"class":304,"line":660},[2684],{"type":53,"tag":302,"props":2685,"children":2686},{},[2687],{"type":59,"value":2688},"list.forEach { item ->\n",{"type":53,"tag":302,"props":2690,"children":2691},{"class":304,"line":668},[2692],{"type":53,"tag":302,"props":2693,"children":2694},{},[2695],{"type":59,"value":2696},"    if (item.isEmpty()) return  \u002F\u002F Returns from outer function!\n",{"type":53,"tag":302,"props":2698,"children":2699},{"class":304,"line":677},[2700],{"type":53,"tag":302,"props":2701,"children":2702},{},[2703],{"type":59,"value":525},{"type":53,"tag":302,"props":2705,"children":2706},{"class":304,"line":686},[2707],{"type":53,"tag":302,"props":2708,"children":2709},{"emptyLinePlaceholder":336},[2710],{"type":59,"value":339},{"type":53,"tag":302,"props":2712,"children":2713},{"class":304,"line":695},[2714],{"type":53,"tag":302,"props":2715,"children":2716},{},[2717],{"type":59,"value":2718},"\u002F\u002F ✅ Correct: Use return@forEach\n",{"type":53,"tag":302,"props":2720,"children":2721},{"class":304,"line":704},[2722],{"type":53,"tag":302,"props":2723,"children":2724},{},[2725],{"type":59,"value":2688},{"type":53,"tag":302,"props":2727,"children":2728},{"class":304,"line":713},[2729],{"type":53,"tag":302,"props":2730,"children":2731},{},[2732],{"type":59,"value":2733},"    if (item.isEmpty()) return@forEach\n",{"type":53,"tag":302,"props":2735,"children":2736},{"class":304,"line":721},[2737],{"type":53,"tag":302,"props":2738,"children":2739},{},[2740],{"type":59,"value":525},{"type":53,"tag":258,"props":2742,"children":2744},{"id":2743},"_36-server-response-data-class-fields-must-be-nullable",[2745],{"type":59,"value":2746},"3.6 Server Response Data Class Fields Must Be Nullable",{"type":53,"tag":265,"props":2748,"children":2750},{"className":440,"code":2749,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Fields declared as non-null (server may not return them)\ndata class UserResponse(\n    val id: String = \"\",\n    val name: String = \"\",\n    val avatar: String = \"\"\n)\n\n\u002F\u002F ✅ Correct: All fields declared as nullable\ndata class UserResponse(\n    @SerializedName(\"id\")\n    val id: String? = null,\n    @SerializedName(\"name\")\n    val name: String? = null,\n    @SerializedName(\"avatar\")\n    val avatar: String? = null\n)\n",[2751],{"type":53,"tag":137,"props":2752,"children":2753},{"__ignoreMap":273},[2754,2762,2770,2778,2786,2794,2801,2808,2816,2823,2831,2839,2847,2855,2863,2871],{"type":53,"tag":302,"props":2755,"children":2756},{"class":304,"line":305},[2757],{"type":53,"tag":302,"props":2758,"children":2759},{},[2760],{"type":59,"value":2761},"\u002F\u002F ❌ Wrong: Fields declared as non-null (server may not return them)\n",{"type":53,"tag":302,"props":2763,"children":2764},{"class":304,"line":314},[2765],{"type":53,"tag":302,"props":2766,"children":2767},{},[2768],{"type":59,"value":2769},"data class UserResponse(\n",{"type":53,"tag":302,"props":2771,"children":2772},{"class":304,"line":323},[2773],{"type":53,"tag":302,"props":2774,"children":2775},{},[2776],{"type":59,"value":2777},"    val id: String = \"\",\n",{"type":53,"tag":302,"props":2779,"children":2780},{"class":304,"line":332},[2781],{"type":53,"tag":302,"props":2782,"children":2783},{},[2784],{"type":59,"value":2785},"    val name: String = \"\",\n",{"type":53,"tag":302,"props":2787,"children":2788},{"class":304,"line":342},[2789],{"type":53,"tag":302,"props":2790,"children":2791},{},[2792],{"type":59,"value":2793},"    val avatar: String = \"\"\n",{"type":53,"tag":302,"props":2795,"children":2796},{"class":304,"line":351},[2797],{"type":53,"tag":302,"props":2798,"children":2799},{},[2800],{"type":59,"value":2568},{"type":53,"tag":302,"props":2802,"children":2803},{"class":304,"line":360},[2804],{"type":53,"tag":302,"props":2805,"children":2806},{"emptyLinePlaceholder":336},[2807],{"type":59,"value":339},{"type":53,"tag":302,"props":2809,"children":2810},{"class":304,"line":369},[2811],{"type":53,"tag":302,"props":2812,"children":2813},{},[2814],{"type":59,"value":2815},"\u002F\u002F ✅ Correct: All fields declared as nullable\n",{"type":53,"tag":302,"props":2817,"children":2818},{"class":304,"line":377},[2819],{"type":53,"tag":302,"props":2820,"children":2821},{},[2822],{"type":59,"value":2769},{"type":53,"tag":302,"props":2824,"children":2825},{"class":304,"line":386},[2826],{"type":53,"tag":302,"props":2827,"children":2828},{},[2829],{"type":59,"value":2830},"    @SerializedName(\"id\")\n",{"type":53,"tag":302,"props":2832,"children":2833},{"class":304,"line":395},[2834],{"type":53,"tag":302,"props":2835,"children":2836},{},[2837],{"type":59,"value":2838},"    val id: String? = null,\n",{"type":53,"tag":302,"props":2840,"children":2841},{"class":304,"line":642},[2842],{"type":53,"tag":302,"props":2843,"children":2844},{},[2845],{"type":59,"value":2846},"    @SerializedName(\"name\")\n",{"type":53,"tag":302,"props":2848,"children":2849},{"class":304,"line":651},[2850],{"type":53,"tag":302,"props":2851,"children":2852},{},[2853],{"type":59,"value":2854},"    val name: String? = null,\n",{"type":53,"tag":302,"props":2856,"children":2857},{"class":304,"line":660},[2858],{"type":53,"tag":302,"props":2859,"children":2860},{},[2861],{"type":59,"value":2862},"    @SerializedName(\"avatar\")\n",{"type":53,"tag":302,"props":2864,"children":2865},{"class":304,"line":668},[2866],{"type":53,"tag":302,"props":2867,"children":2868},{},[2869],{"type":59,"value":2870},"    val avatar: String? = null\n",{"type":53,"tag":302,"props":2872,"children":2873},{"class":304,"line":677},[2874],{"type":53,"tag":302,"props":2875,"children":2876},{},[2877],{"type":59,"value":2568},{"type":53,"tag":258,"props":2879,"children":2881},{"id":2880},"_37-lifecycle-resource-management",[2882],{"type":59,"value":2883},"3.7 Lifecycle Resource Management",{"type":53,"tag":265,"props":2885,"children":2887},{"className":440,"code":2886,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Only adding Observer, not removing\nclass MyView : View {\n    override fun onAttachedToWindow() {\n        super.onAttachedToWindow()\n        activity?.lifecycle?.addObserver(this)\n    }\n    \u002F\u002F Memory leak!\n}\n\n\u002F\u002F ✅ Correct: Paired add and remove\nclass MyView : View {\n    override fun onAttachedToWindow() {\n        super.onAttachedToWindow()\n        activity?.lifecycle?.addObserver(this)\n    }\n\n    override fun onDetachedFromWindow() {\n        activity?.lifecycle?.removeObserver(this)\n        super.onDetachedFromWindow()\n    }\n}\n",[2888],{"type":53,"tag":137,"props":2889,"children":2890},{"__ignoreMap":273},[2891,2899,2907,2915,2923,2931,2938,2946,2953,2960,2968,2975,2982,2989,2996,3003,3010,3018,3026,3034,3041],{"type":53,"tag":302,"props":2892,"children":2893},{"class":304,"line":305},[2894],{"type":53,"tag":302,"props":2895,"children":2896},{},[2897],{"type":59,"value":2898},"\u002F\u002F ❌ Wrong: Only adding Observer, not removing\n",{"type":53,"tag":302,"props":2900,"children":2901},{"class":304,"line":314},[2902],{"type":53,"tag":302,"props":2903,"children":2904},{},[2905],{"type":59,"value":2906},"class MyView : View {\n",{"type":53,"tag":302,"props":2908,"children":2909},{"class":304,"line":323},[2910],{"type":53,"tag":302,"props":2911,"children":2912},{},[2913],{"type":59,"value":2914},"    override fun onAttachedToWindow() {\n",{"type":53,"tag":302,"props":2916,"children":2917},{"class":304,"line":332},[2918],{"type":53,"tag":302,"props":2919,"children":2920},{},[2921],{"type":59,"value":2922},"        super.onAttachedToWindow()\n",{"type":53,"tag":302,"props":2924,"children":2925},{"class":304,"line":342},[2926],{"type":53,"tag":302,"props":2927,"children":2928},{},[2929],{"type":59,"value":2930},"        activity?.lifecycle?.addObserver(this)\n",{"type":53,"tag":302,"props":2932,"children":2933},{"class":304,"line":351},[2934],{"type":53,"tag":302,"props":2935,"children":2936},{},[2937],{"type":59,"value":864},{"type":53,"tag":302,"props":2939,"children":2940},{"class":304,"line":360},[2941],{"type":53,"tag":302,"props":2942,"children":2943},{},[2944],{"type":59,"value":2945},"    \u002F\u002F Memory leak!\n",{"type":53,"tag":302,"props":2947,"children":2948},{"class":304,"line":369},[2949],{"type":53,"tag":302,"props":2950,"children":2951},{},[2952],{"type":59,"value":525},{"type":53,"tag":302,"props":2954,"children":2955},{"class":304,"line":377},[2956],{"type":53,"tag":302,"props":2957,"children":2958},{"emptyLinePlaceholder":336},[2959],{"type":59,"value":339},{"type":53,"tag":302,"props":2961,"children":2962},{"class":304,"line":386},[2963],{"type":53,"tag":302,"props":2964,"children":2965},{},[2966],{"type":59,"value":2967},"\u002F\u002F ✅ Correct: Paired add and remove\n",{"type":53,"tag":302,"props":2969,"children":2970},{"class":304,"line":395},[2971],{"type":53,"tag":302,"props":2972,"children":2973},{},[2974],{"type":59,"value":2906},{"type":53,"tag":302,"props":2976,"children":2977},{"class":304,"line":642},[2978],{"type":53,"tag":302,"props":2979,"children":2980},{},[2981],{"type":59,"value":2914},{"type":53,"tag":302,"props":2983,"children":2984},{"class":304,"line":651},[2985],{"type":53,"tag":302,"props":2986,"children":2987},{},[2988],{"type":59,"value":2922},{"type":53,"tag":302,"props":2990,"children":2991},{"class":304,"line":660},[2992],{"type":53,"tag":302,"props":2993,"children":2994},{},[2995],{"type":59,"value":2930},{"type":53,"tag":302,"props":2997,"children":2998},{"class":304,"line":668},[2999],{"type":53,"tag":302,"props":3000,"children":3001},{},[3002],{"type":59,"value":864},{"type":53,"tag":302,"props":3004,"children":3005},{"class":304,"line":677},[3006],{"type":53,"tag":302,"props":3007,"children":3008},{"emptyLinePlaceholder":336},[3009],{"type":59,"value":339},{"type":53,"tag":302,"props":3011,"children":3012},{"class":304,"line":686},[3013],{"type":53,"tag":302,"props":3014,"children":3015},{},[3016],{"type":59,"value":3017},"    override fun onDetachedFromWindow() {\n",{"type":53,"tag":302,"props":3019,"children":3020},{"class":304,"line":695},[3021],{"type":53,"tag":302,"props":3022,"children":3023},{},[3024],{"type":59,"value":3025},"        activity?.lifecycle?.removeObserver(this)\n",{"type":53,"tag":302,"props":3027,"children":3028},{"class":304,"line":704},[3029],{"type":53,"tag":302,"props":3030,"children":3031},{},[3032],{"type":59,"value":3033},"        super.onDetachedFromWindow()\n",{"type":53,"tag":302,"props":3035,"children":3036},{"class":304,"line":713},[3037],{"type":53,"tag":302,"props":3038,"children":3039},{},[3040],{"type":59,"value":864},{"type":53,"tag":302,"props":3042,"children":3043},{"class":304,"line":721},[3044],{"type":53,"tag":302,"props":3045,"children":3046},{},[3047],{"type":59,"value":525},{"type":53,"tag":258,"props":3049,"children":3051},{"id":3050},"_38-logging-level-usage",[3052],{"type":59,"value":3053},"3.8 Logging Level Usage",{"type":53,"tag":265,"props":3055,"children":3057},{"className":440,"code":3056,"language":15,"meta":273,"style":273},"import android.util.Log\n\n\u002F\u002F Info: Key checkpoints in normal flow\nLog.i(TAG, \"loadData: started, userId = $userId\")\n\n\u002F\u002F Warning: Abnormal but recoverable situations\nLog.w(TAG, \"loadData: cache miss, fallback to network\")\n\n\u002F\u002F Error: Failure\u002Ferror situations\nLog.e(TAG, \"loadData failed: ${error.message}\")\n",[3058],{"type":53,"tag":137,"props":3059,"children":3060},{"__ignoreMap":273},[3061,3069,3076,3084,3092,3099,3107,3115,3122,3130],{"type":53,"tag":302,"props":3062,"children":3063},{"class":304,"line":305},[3064],{"type":53,"tag":302,"props":3065,"children":3066},{},[3067],{"type":59,"value":3068},"import android.util.Log\n",{"type":53,"tag":302,"props":3070,"children":3071},{"class":304,"line":314},[3072],{"type":53,"tag":302,"props":3073,"children":3074},{"emptyLinePlaceholder":336},[3075],{"type":59,"value":339},{"type":53,"tag":302,"props":3077,"children":3078},{"class":304,"line":323},[3079],{"type":53,"tag":302,"props":3080,"children":3081},{},[3082],{"type":59,"value":3083},"\u002F\u002F Info: Key checkpoints in normal flow\n",{"type":53,"tag":302,"props":3085,"children":3086},{"class":304,"line":332},[3087],{"type":53,"tag":302,"props":3088,"children":3089},{},[3090],{"type":59,"value":3091},"Log.i(TAG, \"loadData: started, userId = $userId\")\n",{"type":53,"tag":302,"props":3093,"children":3094},{"class":304,"line":342},[3095],{"type":53,"tag":302,"props":3096,"children":3097},{"emptyLinePlaceholder":336},[3098],{"type":59,"value":339},{"type":53,"tag":302,"props":3100,"children":3101},{"class":304,"line":351},[3102],{"type":53,"tag":302,"props":3103,"children":3104},{},[3105],{"type":59,"value":3106},"\u002F\u002F Warning: Abnormal but recoverable situations\n",{"type":53,"tag":302,"props":3108,"children":3109},{"class":304,"line":360},[3110],{"type":53,"tag":302,"props":3111,"children":3112},{},[3113],{"type":59,"value":3114},"Log.w(TAG, \"loadData: cache miss, fallback to network\")\n",{"type":53,"tag":302,"props":3116,"children":3117},{"class":304,"line":369},[3118],{"type":53,"tag":302,"props":3119,"children":3120},{"emptyLinePlaceholder":336},[3121],{"type":59,"value":339},{"type":53,"tag":302,"props":3123,"children":3124},{"class":304,"line":377},[3125],{"type":53,"tag":302,"props":3126,"children":3127},{},[3128],{"type":59,"value":3129},"\u002F\u002F Error: Failure\u002Ferror situations\n",{"type":53,"tag":302,"props":3131,"children":3132},{"class":304,"line":386},[3133],{"type":53,"tag":302,"props":3134,"children":3135},{},[3136],{"type":59,"value":3137},"Log.e(TAG, \"loadData failed: ${error.message}\")\n",{"type":53,"tag":68,"props":3139,"children":3140},{},[3141,3157],{"type":53,"tag":72,"props":3142,"children":3143},{},[3144],{"type":53,"tag":76,"props":3145,"children":3146},{},[3147,3152],{"type":53,"tag":80,"props":3148,"children":3149},{},[3150],{"type":59,"value":3151},"Level",{"type":53,"tag":80,"props":3153,"children":3154},{},[3155],{"type":59,"value":3156},"Use Case",{"type":53,"tag":96,"props":3158,"children":3159},{},[3160,3179,3198],{"type":53,"tag":76,"props":3161,"children":3162},{},[3163,3174],{"type":53,"tag":103,"props":3164,"children":3165},{},[3166,3172],{"type":53,"tag":137,"props":3167,"children":3169},{"className":3168},[],[3170],{"type":59,"value":3171},"i",{"type":59,"value":3173}," (Info)",{"type":53,"tag":103,"props":3175,"children":3176},{},[3177],{"type":59,"value":3178},"Normal flow, method entry, key parameters",{"type":53,"tag":76,"props":3180,"children":3181},{},[3182,3193],{"type":53,"tag":103,"props":3183,"children":3184},{},[3185,3191],{"type":53,"tag":137,"props":3186,"children":3188},{"className":3187},[],[3189],{"type":59,"value":3190},"w",{"type":59,"value":3192}," (Warning)",{"type":53,"tag":103,"props":3194,"children":3195},{},[3196],{"type":59,"value":3197},"Recoverable exceptions, fallback handling, null returns",{"type":53,"tag":76,"props":3199,"children":3200},{},[3201,3212],{"type":53,"tag":103,"props":3202,"children":3203},{},[3204,3210],{"type":53,"tag":137,"props":3205,"children":3207},{"className":3206},[],[3208],{"type":59,"value":3209},"e",{"type":59,"value":3211}," (Error)",{"type":53,"tag":103,"props":3213,"children":3214},{},[3215],{"type":59,"value":3216},"Request failures, caught exceptions, unrecoverable errors",{"type":53,"tag":277,"props":3218,"children":3219},{},[],{"type":53,"tag":54,"props":3221,"children":3223},{"id":3222},"_4-jetpack-compose-standards",[3224],{"type":59,"value":3225},"4. Jetpack Compose Standards",{"type":53,"tag":258,"props":3227,"children":3229},{"id":3228},"_41-composable-context-rules",[3230],{"type":59,"value":3231},"4.1 @Composable Context Rules",{"type":53,"tag":265,"props":3233,"children":3235},{"className":440,"code":3234,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Calling Composable from non-Composable function\nfun showError(message: String) {\n    Text(message)  \u002F\u002F Compile error!\n}\n\n\u002F\u002F ✅ Correct: Mark as @Composable\n@Composable\nfun ErrorMessage(message: String) {\n    Text(message)\n}\n\n\u002F\u002F ❌ Wrong: Using suspend outside LaunchedEffect\n@Composable\nfun MyScreen() {\n    val data = fetchData()  \u002F\u002F Error!\n}\n\n\u002F\u002F ✅ Correct: Use LaunchedEffect\n@Composable\nfun MyScreen() {\n    var data by remember { mutableStateOf\u003CData?>(null) }\n    LaunchedEffect(Unit) {\n        data = fetchData()\n    }\n}\n",[3236],{"type":53,"tag":137,"props":3237,"children":3238},{"__ignoreMap":273},[3239,3247,3255,3263,3270,3277,3285,3293,3301,3309,3316,3323,3331,3338,3346,3354,3361,3368,3376,3383,3390,3398,3406,3414,3421],{"type":53,"tag":302,"props":3240,"children":3241},{"class":304,"line":305},[3242],{"type":53,"tag":302,"props":3243,"children":3244},{},[3245],{"type":59,"value":3246},"\u002F\u002F ❌ Wrong: Calling Composable from non-Composable function\n",{"type":53,"tag":302,"props":3248,"children":3249},{"class":304,"line":314},[3250],{"type":53,"tag":302,"props":3251,"children":3252},{},[3253],{"type":59,"value":3254},"fun showError(message: String) {\n",{"type":53,"tag":302,"props":3256,"children":3257},{"class":304,"line":323},[3258],{"type":53,"tag":302,"props":3259,"children":3260},{},[3261],{"type":59,"value":3262},"    Text(message)  \u002F\u002F Compile error!\n",{"type":53,"tag":302,"props":3264,"children":3265},{"class":304,"line":332},[3266],{"type":53,"tag":302,"props":3267,"children":3268},{},[3269],{"type":59,"value":525},{"type":53,"tag":302,"props":3271,"children":3272},{"class":304,"line":342},[3273],{"type":53,"tag":302,"props":3274,"children":3275},{"emptyLinePlaceholder":336},[3276],{"type":59,"value":339},{"type":53,"tag":302,"props":3278,"children":3279},{"class":304,"line":351},[3280],{"type":53,"tag":302,"props":3281,"children":3282},{},[3283],{"type":59,"value":3284},"\u002F\u002F ✅ Correct: Mark as @Composable\n",{"type":53,"tag":302,"props":3286,"children":3287},{"class":304,"line":360},[3288],{"type":53,"tag":302,"props":3289,"children":3290},{},[3291],{"type":59,"value":3292},"@Composable\n",{"type":53,"tag":302,"props":3294,"children":3295},{"class":304,"line":369},[3296],{"type":53,"tag":302,"props":3297,"children":3298},{},[3299],{"type":59,"value":3300},"fun ErrorMessage(message: String) {\n",{"type":53,"tag":302,"props":3302,"children":3303},{"class":304,"line":377},[3304],{"type":53,"tag":302,"props":3305,"children":3306},{},[3307],{"type":59,"value":3308},"    Text(message)\n",{"type":53,"tag":302,"props":3310,"children":3311},{"class":304,"line":386},[3312],{"type":53,"tag":302,"props":3313,"children":3314},{},[3315],{"type":59,"value":525},{"type":53,"tag":302,"props":3317,"children":3318},{"class":304,"line":395},[3319],{"type":53,"tag":302,"props":3320,"children":3321},{"emptyLinePlaceholder":336},[3322],{"type":59,"value":339},{"type":53,"tag":302,"props":3324,"children":3325},{"class":304,"line":642},[3326],{"type":53,"tag":302,"props":3327,"children":3328},{},[3329],{"type":59,"value":3330},"\u002F\u002F ❌ Wrong: Using suspend outside LaunchedEffect\n",{"type":53,"tag":302,"props":3332,"children":3333},{"class":304,"line":651},[3334],{"type":53,"tag":302,"props":3335,"children":3336},{},[3337],{"type":59,"value":3292},{"type":53,"tag":302,"props":3339,"children":3340},{"class":304,"line":660},[3341],{"type":53,"tag":302,"props":3342,"children":3343},{},[3344],{"type":59,"value":3345},"fun MyScreen() {\n",{"type":53,"tag":302,"props":3347,"children":3348},{"class":304,"line":668},[3349],{"type":53,"tag":302,"props":3350,"children":3351},{},[3352],{"type":59,"value":3353},"    val data = fetchData()  \u002F\u002F Error!\n",{"type":53,"tag":302,"props":3355,"children":3356},{"class":304,"line":677},[3357],{"type":53,"tag":302,"props":3358,"children":3359},{},[3360],{"type":59,"value":525},{"type":53,"tag":302,"props":3362,"children":3363},{"class":304,"line":686},[3364],{"type":53,"tag":302,"props":3365,"children":3366},{"emptyLinePlaceholder":336},[3367],{"type":59,"value":339},{"type":53,"tag":302,"props":3369,"children":3370},{"class":304,"line":695},[3371],{"type":53,"tag":302,"props":3372,"children":3373},{},[3374],{"type":59,"value":3375},"\u002F\u002F ✅ Correct: Use LaunchedEffect\n",{"type":53,"tag":302,"props":3377,"children":3378},{"class":304,"line":704},[3379],{"type":53,"tag":302,"props":3380,"children":3381},{},[3382],{"type":59,"value":3292},{"type":53,"tag":302,"props":3384,"children":3385},{"class":304,"line":713},[3386],{"type":53,"tag":302,"props":3387,"children":3388},{},[3389],{"type":59,"value":3345},{"type":53,"tag":302,"props":3391,"children":3392},{"class":304,"line":721},[3393],{"type":53,"tag":302,"props":3394,"children":3395},{},[3396],{"type":59,"value":3397},"    var data by remember { mutableStateOf\u003CData?>(null) }\n",{"type":53,"tag":302,"props":3399,"children":3400},{"class":304,"line":730},[3401],{"type":53,"tag":302,"props":3402,"children":3403},{},[3404],{"type":59,"value":3405},"    LaunchedEffect(Unit) {\n",{"type":53,"tag":302,"props":3407,"children":3408},{"class":304,"line":739},[3409],{"type":53,"tag":302,"props":3410,"children":3411},{},[3412],{"type":59,"value":3413},"        data = fetchData()\n",{"type":53,"tag":302,"props":3415,"children":3416},{"class":304,"line":747},[3417],{"type":53,"tag":302,"props":3418,"children":3419},{},[3420],{"type":59,"value":864},{"type":53,"tag":302,"props":3422,"children":3423},{"class":304,"line":756},[3424],{"type":53,"tag":302,"props":3425,"children":3426},{},[3427],{"type":59,"value":525},{"type":53,"tag":258,"props":3429,"children":3431},{"id":3430},"_42-state-management",[3432],{"type":59,"value":3433},"4.2 State Management",{"type":53,"tag":265,"props":3435,"children":3437},{"className":440,"code":3436,"language":15,"meta":273,"style":273},"\u002F\u002F Basic State\nvar count by remember { mutableStateOf(0) }\n\n\u002F\u002F Derived State (avoid redundant computation)\nval isEven by remember { derivedStateOf { count % 2 == 0 } }\n\n\u002F\u002F Persist across recomposition (e.g., scroll position)\nval scrollState = rememberScrollState()\n\n\u002F\u002F State in ViewModel\nclass MyViewModel : ViewModel() {\n    private val _uiState = MutableStateFlow(UiState())\n    val uiState: StateFlow\u003CUiState> = _uiState.asStateFlow()\n}\n",[3438],{"type":53,"tag":137,"props":3439,"children":3440},{"__ignoreMap":273},[3441,3449,3457,3464,3472,3480,3487,3495,3503,3510,3518,3525,3533,3541],{"type":53,"tag":302,"props":3442,"children":3443},{"class":304,"line":305},[3444],{"type":53,"tag":302,"props":3445,"children":3446},{},[3447],{"type":59,"value":3448},"\u002F\u002F Basic State\n",{"type":53,"tag":302,"props":3450,"children":3451},{"class":304,"line":314},[3452],{"type":53,"tag":302,"props":3453,"children":3454},{},[3455],{"type":59,"value":3456},"var count by remember { mutableStateOf(0) }\n",{"type":53,"tag":302,"props":3458,"children":3459},{"class":304,"line":323},[3460],{"type":53,"tag":302,"props":3461,"children":3462},{"emptyLinePlaceholder":336},[3463],{"type":59,"value":339},{"type":53,"tag":302,"props":3465,"children":3466},{"class":304,"line":332},[3467],{"type":53,"tag":302,"props":3468,"children":3469},{},[3470],{"type":59,"value":3471},"\u002F\u002F Derived State (avoid redundant computation)\n",{"type":53,"tag":302,"props":3473,"children":3474},{"class":304,"line":342},[3475],{"type":53,"tag":302,"props":3476,"children":3477},{},[3478],{"type":59,"value":3479},"val isEven by remember { derivedStateOf { count % 2 == 0 } }\n",{"type":53,"tag":302,"props":3481,"children":3482},{"class":304,"line":351},[3483],{"type":53,"tag":302,"props":3484,"children":3485},{"emptyLinePlaceholder":336},[3486],{"type":59,"value":339},{"type":53,"tag":302,"props":3488,"children":3489},{"class":304,"line":360},[3490],{"type":53,"tag":302,"props":3491,"children":3492},{},[3493],{"type":59,"value":3494},"\u002F\u002F Persist across recomposition (e.g., scroll position)\n",{"type":53,"tag":302,"props":3496,"children":3497},{"class":304,"line":369},[3498],{"type":53,"tag":302,"props":3499,"children":3500},{},[3501],{"type":59,"value":3502},"val scrollState = rememberScrollState()\n",{"type":53,"tag":302,"props":3504,"children":3505},{"class":304,"line":377},[3506],{"type":53,"tag":302,"props":3507,"children":3508},{"emptyLinePlaceholder":336},[3509],{"type":59,"value":339},{"type":53,"tag":302,"props":3511,"children":3512},{"class":304,"line":386},[3513],{"type":53,"tag":302,"props":3514,"children":3515},{},[3516],{"type":59,"value":3517},"\u002F\u002F State in ViewModel\n",{"type":53,"tag":302,"props":3519,"children":3520},{"class":304,"line":395},[3521],{"type":53,"tag":302,"props":3522,"children":3523},{},[3524],{"type":59,"value":2597},{"type":53,"tag":302,"props":3526,"children":3527},{"class":304,"line":642},[3528],{"type":53,"tag":302,"props":3529,"children":3530},{},[3531],{"type":59,"value":3532},"    private val _uiState = MutableStateFlow(UiState())\n",{"type":53,"tag":302,"props":3534,"children":3535},{"class":304,"line":651},[3536],{"type":53,"tag":302,"props":3537,"children":3538},{},[3539],{"type":59,"value":3540},"    val uiState: StateFlow\u003CUiState> = _uiState.asStateFlow()\n",{"type":53,"tag":302,"props":3542,"children":3543},{"class":304,"line":660},[3544],{"type":53,"tag":302,"props":3545,"children":3546},{},[3547],{"type":59,"value":525},{"type":53,"tag":258,"props":3549,"children":3551},{"id":3550},"_43-common-compose-mistakes",[3552],{"type":59,"value":3553},"4.3 Common Compose Mistakes",{"type":53,"tag":265,"props":3555,"children":3557},{"className":440,"code":3556,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Creating objects in Composable (created on every recomposition)\n@Composable\nfun MyScreen() {\n    val viewModel = MyViewModel()  \u002F\u002F Wrong!\n}\n\n\u002F\u002F ✅ Correct: Use viewModel() or remember\n@Composable\nfun MyScreen(viewModel: MyViewModel = viewModel()) {\n    \u002F\u002F ...\n}\n",[3558],{"type":53,"tag":137,"props":3559,"children":3560},{"__ignoreMap":273},[3561,3569,3576,3583,3591,3598,3605,3613,3620,3628,3636],{"type":53,"tag":302,"props":3562,"children":3563},{"class":304,"line":305},[3564],{"type":53,"tag":302,"props":3565,"children":3566},{},[3567],{"type":59,"value":3568},"\u002F\u002F ❌ Wrong: Creating objects in Composable (created on every recomposition)\n",{"type":53,"tag":302,"props":3570,"children":3571},{"class":304,"line":314},[3572],{"type":53,"tag":302,"props":3573,"children":3574},{},[3575],{"type":59,"value":3292},{"type":53,"tag":302,"props":3577,"children":3578},{"class":304,"line":323},[3579],{"type":53,"tag":302,"props":3580,"children":3581},{},[3582],{"type":59,"value":3345},{"type":53,"tag":302,"props":3584,"children":3585},{"class":304,"line":332},[3586],{"type":53,"tag":302,"props":3587,"children":3588},{},[3589],{"type":59,"value":3590},"    val viewModel = MyViewModel()  \u002F\u002F Wrong!\n",{"type":53,"tag":302,"props":3592,"children":3593},{"class":304,"line":342},[3594],{"type":53,"tag":302,"props":3595,"children":3596},{},[3597],{"type":59,"value":525},{"type":53,"tag":302,"props":3599,"children":3600},{"class":304,"line":351},[3601],{"type":53,"tag":302,"props":3602,"children":3603},{"emptyLinePlaceholder":336},[3604],{"type":59,"value":339},{"type":53,"tag":302,"props":3606,"children":3607},{"class":304,"line":360},[3608],{"type":53,"tag":302,"props":3609,"children":3610},{},[3611],{"type":59,"value":3612},"\u002F\u002F ✅ Correct: Use viewModel() or remember\n",{"type":53,"tag":302,"props":3614,"children":3615},{"class":304,"line":369},[3616],{"type":53,"tag":302,"props":3617,"children":3618},{},[3619],{"type":59,"value":3292},{"type":53,"tag":302,"props":3621,"children":3622},{"class":304,"line":377},[3623],{"type":53,"tag":302,"props":3624,"children":3625},{},[3626],{"type":59,"value":3627},"fun MyScreen(viewModel: MyViewModel = viewModel()) {\n",{"type":53,"tag":302,"props":3629,"children":3630},{"class":304,"line":386},[3631],{"type":53,"tag":302,"props":3632,"children":3633},{},[3634],{"type":59,"value":3635},"    \u002F\u002F ...\n",{"type":53,"tag":302,"props":3637,"children":3638},{"class":304,"line":395},[3639],{"type":53,"tag":302,"props":3640,"children":3641},{},[3642],{"type":59,"value":525},{"type":53,"tag":277,"props":3644,"children":3645},{},[],{"type":53,"tag":54,"props":3647,"children":3649},{"id":3648},"_5-resources-icons",[3650],{"type":59,"value":3651},"5. Resources & Icons",{"type":53,"tag":258,"props":3653,"children":3655},{"id":3654},"_51-app-icon-requirements",[3656],{"type":59,"value":3657},"5.1 App Icon Requirements",{"type":53,"tag":62,"props":3659,"children":3660},{},[3661],{"type":59,"value":3662},"Must provide multi-resolution icons:",{"type":53,"tag":68,"props":3664,"children":3665},{},[3666,3687],{"type":53,"tag":72,"props":3667,"children":3668},{},[3669],{"type":53,"tag":76,"props":3670,"children":3671},{},[3672,3677,3682],{"type":53,"tag":80,"props":3673,"children":3674},{},[3675],{"type":59,"value":3676},"Directory",{"type":53,"tag":80,"props":3678,"children":3679},{},[3680],{"type":59,"value":3681},"Size",{"type":53,"tag":80,"props":3683,"children":3684},{},[3685],{"type":59,"value":3686},"Purpose",{"type":53,"tag":96,"props":3688,"children":3689},{},[3690,3708,3726,3744,3762],{"type":53,"tag":76,"props":3691,"children":3692},{},[3693,3698,3703],{"type":53,"tag":103,"props":3694,"children":3695},{},[3696],{"type":59,"value":3697},"mipmap-mdpi",{"type":53,"tag":103,"props":3699,"children":3700},{},[3701],{"type":59,"value":3702},"48x48",{"type":53,"tag":103,"props":3704,"children":3705},{},[3706],{"type":59,"value":3707},"Baseline",{"type":53,"tag":76,"props":3709,"children":3710},{},[3711,3716,3721],{"type":53,"tag":103,"props":3712,"children":3713},{},[3714],{"type":59,"value":3715},"mipmap-hdpi",{"type":53,"tag":103,"props":3717,"children":3718},{},[3719],{"type":59,"value":3720},"72x72",{"type":53,"tag":103,"props":3722,"children":3723},{},[3724],{"type":59,"value":3725},"1.5x",{"type":53,"tag":76,"props":3727,"children":3728},{},[3729,3734,3739],{"type":53,"tag":103,"props":3730,"children":3731},{},[3732],{"type":59,"value":3733},"mipmap-xhdpi",{"type":53,"tag":103,"props":3735,"children":3736},{},[3737],{"type":59,"value":3738},"96x96",{"type":53,"tag":103,"props":3740,"children":3741},{},[3742],{"type":59,"value":3743},"2x",{"type":53,"tag":76,"props":3745,"children":3746},{},[3747,3752,3757],{"type":53,"tag":103,"props":3748,"children":3749},{},[3750],{"type":59,"value":3751},"mipmap-xxhdpi",{"type":53,"tag":103,"props":3753,"children":3754},{},[3755],{"type":59,"value":3756},"144x144",{"type":53,"tag":103,"props":3758,"children":3759},{},[3760],{"type":59,"value":3761},"3x",{"type":53,"tag":76,"props":3763,"children":3764},{},[3765,3770,3775],{"type":53,"tag":103,"props":3766,"children":3767},{},[3768],{"type":59,"value":3769},"mipmap-xxxhdpi",{"type":53,"tag":103,"props":3771,"children":3772},{},[3773],{"type":59,"value":3774},"192x192",{"type":53,"tag":103,"props":3776,"children":3777},{},[3778],{"type":59,"value":3779},"4x",{"type":53,"tag":62,"props":3781,"children":3782},{},[3783],{"type":59,"value":3784},"Recommended: Use Adaptive Icon (Android 8+):",{"type":53,"tag":265,"props":3786,"children":3790},{"className":3787,"code":3788,"language":3789,"meta":273,"style":273},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- res\u002Fmipmap-anydpi-v26\u002Fic_launcher.xml -->\n\u003Cadaptive-icon>\n    \u003Cbackground android:drawable=\"@color\u002Fic_launcher_background\"\u002F>\n    \u003Cforeground android:drawable=\"@mipmap\u002Fic_launcher_foreground\"\u002F>\n\u003C\u002Fadaptive-icon>\n","xml",[3791],{"type":53,"tag":137,"props":3792,"children":3793},{"__ignoreMap":273},[3794,3802,3810,3818,3826],{"type":53,"tag":302,"props":3795,"children":3796},{"class":304,"line":305},[3797],{"type":53,"tag":302,"props":3798,"children":3799},{},[3800],{"type":59,"value":3801},"\u003C!-- res\u002Fmipmap-anydpi-v26\u002Fic_launcher.xml -->\n",{"type":53,"tag":302,"props":3803,"children":3804},{"class":304,"line":314},[3805],{"type":53,"tag":302,"props":3806,"children":3807},{},[3808],{"type":59,"value":3809},"\u003Cadaptive-icon>\n",{"type":53,"tag":302,"props":3811,"children":3812},{"class":304,"line":323},[3813],{"type":53,"tag":302,"props":3814,"children":3815},{},[3816],{"type":59,"value":3817},"    \u003Cbackground android:drawable=\"@color\u002Fic_launcher_background\"\u002F>\n",{"type":53,"tag":302,"props":3819,"children":3820},{"class":304,"line":332},[3821],{"type":53,"tag":302,"props":3822,"children":3823},{},[3824],{"type":59,"value":3825},"    \u003Cforeground android:drawable=\"@mipmap\u002Fic_launcher_foreground\"\u002F>\n",{"type":53,"tag":302,"props":3827,"children":3828},{"class":304,"line":342},[3829],{"type":53,"tag":302,"props":3830,"children":3831},{},[3832],{"type":59,"value":3833},"\u003C\u002Fadaptive-icon>\n",{"type":53,"tag":258,"props":3835,"children":3837},{"id":3836},"_52-resource-naming-conventions",[3838],{"type":59,"value":3839},"5.2 Resource Naming Conventions",{"type":53,"tag":68,"props":3841,"children":3842},{},[3843,3862],{"type":53,"tag":72,"props":3844,"children":3845},{},[3846],{"type":53,"tag":76,"props":3847,"children":3848},{},[3849,3853,3858],{"type":53,"tag":80,"props":3850,"children":3851},{},[3852],{"type":59,"value":1630},{"type":53,"tag":80,"props":3854,"children":3855},{},[3856],{"type":59,"value":3857},"Prefix",{"type":53,"tag":80,"props":3859,"children":3860},{},[3861],{"type":59,"value":1640},{"type":53,"tag":96,"props":3863,"children":3864},{},[3865,3887,3909,3931],{"type":53,"tag":76,"props":3866,"children":3867},{},[3868,3873,3878],{"type":53,"tag":103,"props":3869,"children":3870},{},[3871],{"type":59,"value":3872},"Layout",{"type":53,"tag":103,"props":3874,"children":3875},{},[3876],{"type":59,"value":3877},"layout_",{"type":53,"tag":103,"props":3879,"children":3880},{},[3881],{"type":53,"tag":137,"props":3882,"children":3884},{"className":3883},[],[3885],{"type":59,"value":3886},"layout_main.xml",{"type":53,"tag":76,"props":3888,"children":3889},{},[3890,3895,3900],{"type":53,"tag":103,"props":3891,"children":3892},{},[3893],{"type":59,"value":3894},"Image",{"type":53,"tag":103,"props":3896,"children":3897},{},[3898],{"type":59,"value":3899},"ic_, img_, bg_",{"type":53,"tag":103,"props":3901,"children":3902},{},[3903],{"type":53,"tag":137,"props":3904,"children":3906},{"className":3905},[],[3907],{"type":59,"value":3908},"ic_user.png",{"type":53,"tag":76,"props":3910,"children":3911},{},[3912,3917,3922],{"type":53,"tag":103,"props":3913,"children":3914},{},[3915],{"type":59,"value":3916},"Color",{"type":53,"tag":103,"props":3918,"children":3919},{},[3920],{"type":59,"value":3921},"color_",{"type":53,"tag":103,"props":3923,"children":3924},{},[3925],{"type":53,"tag":137,"props":3926,"children":3928},{"className":3927},[],[3929],{"type":59,"value":3930},"color_primary",{"type":53,"tag":76,"props":3932,"children":3933},{},[3934,3939,3944],{"type":53,"tag":103,"props":3935,"children":3936},{},[3937],{"type":59,"value":3938},"String",{"type":53,"tag":103,"props":3940,"children":3941},{},[3942],{"type":59,"value":3943},"-",{"type":53,"tag":103,"props":3945,"children":3946},{},[3947,3953,3954],{"type":53,"tag":137,"props":3948,"children":3950},{"className":3949},[],[3951],{"type":59,"value":3952},"app_name",{"type":59,"value":1002},{"type":53,"tag":137,"props":3955,"children":3957},{"className":3956},[],[3958],{"type":59,"value":3959},"btn_submit",{"type":53,"tag":258,"props":3961,"children":3963},{"id":3962},"_53-avoid-android-reserved-names-important",[3964],{"type":59,"value":3965},"5.3 Avoid Android Reserved Names (Important)",{"type":53,"tag":62,"props":3967,"children":3968},{},[3969,3971,3976],{"type":59,"value":3970},"Variable names, resource IDs, colors, icons, and XML elements ",{"type":53,"tag":107,"props":3972,"children":3973},{},[3974],{"type":59,"value":3975},"must not",{"type":59,"value":3977}," use Android reserved words or system resource names. Using reserved names causes build errors or resource conflicts.",{"type":53,"tag":62,"props":3979,"children":3980},{},[3981,3986],{"type":53,"tag":107,"props":3982,"children":3983},{},[3984],{"type":59,"value":3985},"Common Reserved Names to Avoid",{"type":59,"value":225},{"type":53,"tag":68,"props":3988,"children":3989},{},[3990,4006],{"type":53,"tag":72,"props":3991,"children":3992},{},[3993],{"type":53,"tag":76,"props":3994,"children":3995},{},[3996,4001],{"type":53,"tag":80,"props":3997,"children":3998},{},[3999],{"type":59,"value":4000},"Category",{"type":53,"tag":80,"props":4002,"children":4003},{},[4004],{"type":59,"value":4005},"Reserved Names (Do NOT Use)",{"type":53,"tag":96,"props":4007,"children":4008},{},[4009,4054,4092,4136,4188],{"type":53,"tag":76,"props":4010,"children":4011},{},[4012,4017],{"type":53,"tag":103,"props":4013,"children":4014},{},[4015],{"type":59,"value":4016},"Colors",{"type":53,"tag":103,"props":4018,"children":4019},{},[4020,4026,4027,4033,4034,4040,4041,4047,4048],{"type":53,"tag":137,"props":4021,"children":4023},{"className":4022},[],[4024],{"type":59,"value":4025},"background",{"type":59,"value":1002},{"type":53,"tag":137,"props":4028,"children":4030},{"className":4029},[],[4031],{"type":59,"value":4032},"foreground",{"type":59,"value":1002},{"type":53,"tag":137,"props":4035,"children":4037},{"className":4036},[],[4038],{"type":59,"value":4039},"transparent",{"type":59,"value":1002},{"type":53,"tag":137,"props":4042,"children":4044},{"className":4043},[],[4045],{"type":59,"value":4046},"white",{"type":59,"value":1002},{"type":53,"tag":137,"props":4049,"children":4051},{"className":4050},[],[4052],{"type":59,"value":4053},"black",{"type":53,"tag":76,"props":4055,"children":4056},{},[4057,4062],{"type":53,"tag":103,"props":4058,"children":4059},{},[4060],{"type":59,"value":4061},"Icons\u002FDrawables",{"type":53,"tag":103,"props":4063,"children":4064},{},[4065,4071,4072,4078,4079,4085,4086],{"type":53,"tag":137,"props":4066,"children":4068},{"className":4067},[],[4069],{"type":59,"value":4070},"icon",{"type":59,"value":1002},{"type":53,"tag":137,"props":4073,"children":4075},{"className":4074},[],[4076],{"type":59,"value":4077},"logo",{"type":59,"value":1002},{"type":53,"tag":137,"props":4080,"children":4082},{"className":4081},[],[4083],{"type":59,"value":4084},"image",{"type":59,"value":1002},{"type":53,"tag":137,"props":4087,"children":4089},{"className":4088},[],[4090],{"type":59,"value":4091},"drawable",{"type":53,"tag":76,"props":4093,"children":4094},{},[4095,4100],{"type":53,"tag":103,"props":4096,"children":4097},{},[4098],{"type":59,"value":4099},"Views",{"type":53,"tag":103,"props":4101,"children":4102},{},[4103,4109,4110,4115,4116,4122,4123,4129,4130],{"type":53,"tag":137,"props":4104,"children":4106},{"className":4105},[],[4107],{"type":59,"value":4108},"view",{"type":59,"value":1002},{"type":53,"tag":137,"props":4111,"children":4113},{"className":4112},[],[4114],{"type":59,"value":59},{"type":59,"value":1002},{"type":53,"tag":137,"props":4117,"children":4119},{"className":4118},[],[4120],{"type":59,"value":4121},"button",{"type":59,"value":1002},{"type":53,"tag":137,"props":4124,"children":4126},{"className":4125},[],[4127],{"type":59,"value":4128},"layout",{"type":59,"value":1002},{"type":53,"tag":137,"props":4131,"children":4133},{"className":4132},[],[4134],{"type":59,"value":4135},"container",{"type":53,"tag":76,"props":4137,"children":4138},{},[4139,4144],{"type":53,"tag":103,"props":4140,"children":4141},{},[4142],{"type":59,"value":4143},"Attributes",{"type":53,"tag":103,"props":4145,"children":4146},{},[4147,4153,4154,4160,4161,4167,4168,4174,4175,4181,4182],{"type":53,"tag":137,"props":4148,"children":4150},{"className":4149},[],[4151],{"type":59,"value":4152},"id",{"type":59,"value":1002},{"type":53,"tag":137,"props":4155,"children":4157},{"className":4156},[],[4158],{"type":59,"value":4159},"name",{"type":59,"value":1002},{"type":53,"tag":137,"props":4162,"children":4164},{"className":4163},[],[4165],{"type":59,"value":4166},"type",{"type":59,"value":1002},{"type":53,"tag":137,"props":4169,"children":4171},{"className":4170},[],[4172],{"type":59,"value":4173},"style",{"type":59,"value":1002},{"type":53,"tag":137,"props":4176,"children":4178},{"className":4177},[],[4179],{"type":59,"value":4180},"theme",{"type":59,"value":1002},{"type":53,"tag":137,"props":4183,"children":4185},{"className":4184},[],[4186],{"type":59,"value":4187},"color",{"type":53,"tag":76,"props":4189,"children":4190},{},[4191,4196],{"type":53,"tag":103,"props":4192,"children":4193},{},[4194],{"type":59,"value":4195},"System",{"type":53,"tag":103,"props":4197,"children":4198},{},[4199,4205,4206,4211,4212,4218,4219,4225,4226],{"type":53,"tag":137,"props":4200,"children":4202},{"className":4201},[],[4203],{"type":59,"value":4204},"app",{"type":59,"value":1002},{"type":53,"tag":137,"props":4207,"children":4209},{"className":4208},[],[4210],{"type":59,"value":19},{"type":59,"value":1002},{"type":53,"tag":137,"props":4213,"children":4215},{"className":4214},[],[4216],{"type":59,"value":4217},"content",{"type":59,"value":1002},{"type":53,"tag":137,"props":4220,"children":4222},{"className":4221},[],[4223],{"type":59,"value":4224},"data",{"type":59,"value":1002},{"type":53,"tag":137,"props":4227,"children":4229},{"className":4228},[],[4230],{"type":59,"value":4231},"action",{"type":53,"tag":62,"props":4233,"children":4234},{},[4235,4240],{"type":53,"tag":107,"props":4236,"children":4237},{},[4238],{"type":59,"value":4239},"Examples",{"type":59,"value":225},{"type":53,"tag":265,"props":4242,"children":4244},{"className":3787,"code":4243,"language":3789,"meta":273,"style":273},"\u003C!-- ❌ Wrong: Using reserved names -->\n\u003Ccolor name=\"background\">#FFFFFF\u003C\u002Fcolor>\n\u003Ccolor name=\"icon\">#000000\u003C\u002Fcolor>\n\n\u003C!-- ✅ Correct: Add prefix or specific naming -->\n\u003Ccolor name=\"app_background\">#FFFFFF\u003C\u002Fcolor>\n\u003Ccolor name=\"icon_primary\">#000000\u003C\u002Fcolor>\n",[4245],{"type":53,"tag":137,"props":4246,"children":4247},{"__ignoreMap":273},[4248,4256,4264,4272,4279,4287,4295],{"type":53,"tag":302,"props":4249,"children":4250},{"class":304,"line":305},[4251],{"type":53,"tag":302,"props":4252,"children":4253},{},[4254],{"type":59,"value":4255},"\u003C!-- ❌ Wrong: Using reserved names -->\n",{"type":53,"tag":302,"props":4257,"children":4258},{"class":304,"line":314},[4259],{"type":53,"tag":302,"props":4260,"children":4261},{},[4262],{"type":59,"value":4263},"\u003Ccolor name=\"background\">#FFFFFF\u003C\u002Fcolor>\n",{"type":53,"tag":302,"props":4265,"children":4266},{"class":304,"line":323},[4267],{"type":53,"tag":302,"props":4268,"children":4269},{},[4270],{"type":59,"value":4271},"\u003Ccolor name=\"icon\">#000000\u003C\u002Fcolor>\n",{"type":53,"tag":302,"props":4273,"children":4274},{"class":304,"line":332},[4275],{"type":53,"tag":302,"props":4276,"children":4277},{"emptyLinePlaceholder":336},[4278],{"type":59,"value":339},{"type":53,"tag":302,"props":4280,"children":4281},{"class":304,"line":342},[4282],{"type":53,"tag":302,"props":4283,"children":4284},{},[4285],{"type":59,"value":4286},"\u003C!-- ✅ Correct: Add prefix or specific naming -->\n",{"type":53,"tag":302,"props":4288,"children":4289},{"class":304,"line":351},[4290],{"type":53,"tag":302,"props":4291,"children":4292},{},[4293],{"type":59,"value":4294},"\u003Ccolor name=\"app_background\">#FFFFFF\u003C\u002Fcolor>\n",{"type":53,"tag":302,"props":4296,"children":4297},{"class":304,"line":360},[4298],{"type":53,"tag":302,"props":4299,"children":4300},{},[4301],{"type":59,"value":4302},"\u003Ccolor name=\"icon_primary\">#000000\u003C\u002Fcolor>\n",{"type":53,"tag":265,"props":4304,"children":4306},{"className":440,"code":4305,"language":15,"meta":273,"style":273},"\u002F\u002F ❌ Wrong: Variable names conflict with system\nval icon = R.drawable.my_icon\nval background = Color.White\n\n\u002F\u002F ✅ Correct: Use descriptive names\nval appIcon = R.drawable.my_icon\nval screenBackground = Color.White\n",[4307],{"type":53,"tag":137,"props":4308,"children":4309},{"__ignoreMap":273},[4310,4318,4326,4334,4341,4349,4357],{"type":53,"tag":302,"props":4311,"children":4312},{"class":304,"line":305},[4313],{"type":53,"tag":302,"props":4314,"children":4315},{},[4316],{"type":59,"value":4317},"\u002F\u002F ❌ Wrong: Variable names conflict with system\n",{"type":53,"tag":302,"props":4319,"children":4320},{"class":304,"line":314},[4321],{"type":53,"tag":302,"props":4322,"children":4323},{},[4324],{"type":59,"value":4325},"val icon = R.drawable.my_icon\n",{"type":53,"tag":302,"props":4327,"children":4328},{"class":304,"line":323},[4329],{"type":53,"tag":302,"props":4330,"children":4331},{},[4332],{"type":59,"value":4333},"val background = Color.White\n",{"type":53,"tag":302,"props":4335,"children":4336},{"class":304,"line":332},[4337],{"type":53,"tag":302,"props":4338,"children":4339},{"emptyLinePlaceholder":336},[4340],{"type":59,"value":339},{"type":53,"tag":302,"props":4342,"children":4343},{"class":304,"line":342},[4344],{"type":53,"tag":302,"props":4345,"children":4346},{},[4347],{"type":59,"value":4348},"\u002F\u002F ✅ Correct: Use descriptive names\n",{"type":53,"tag":302,"props":4350,"children":4351},{"class":304,"line":351},[4352],{"type":53,"tag":302,"props":4353,"children":4354},{},[4355],{"type":59,"value":4356},"val appIcon = R.drawable.my_icon\n",{"type":53,"tag":302,"props":4358,"children":4359},{"class":304,"line":360},[4360],{"type":53,"tag":302,"props":4361,"children":4362},{},[4363],{"type":59,"value":4364},"val screenBackground = Color.White\n",{"type":53,"tag":265,"props":4366,"children":4368},{"className":3787,"code":4367,"language":3789,"meta":273,"style":273},"\u003C!-- ❌ Wrong: Drawable name conflicts -->\n\u003CImageView android:src=\"@drawable\u002Ficon\" \u002F>\n\n\u003C!-- ✅ Correct: Add prefix -->\n\u003CImageView android:src=\"@drawable\u002Fic_home\" \u002F>\n",[4369],{"type":53,"tag":137,"props":4370,"children":4371},{"__ignoreMap":273},[4372,4380,4388,4395,4403],{"type":53,"tag":302,"props":4373,"children":4374},{"class":304,"line":305},[4375],{"type":53,"tag":302,"props":4376,"children":4377},{},[4378],{"type":59,"value":4379},"\u003C!-- ❌ Wrong: Drawable name conflicts -->\n",{"type":53,"tag":302,"props":4381,"children":4382},{"class":304,"line":314},[4383],{"type":53,"tag":302,"props":4384,"children":4385},{},[4386],{"type":59,"value":4387},"\u003CImageView android:src=\"@drawable\u002Ficon\" \u002F>\n",{"type":53,"tag":302,"props":4389,"children":4390},{"class":304,"line":323},[4391],{"type":53,"tag":302,"props":4392,"children":4393},{"emptyLinePlaceholder":336},[4394],{"type":59,"value":339},{"type":53,"tag":302,"props":4396,"children":4397},{"class":304,"line":332},[4398],{"type":53,"tag":302,"props":4399,"children":4400},{},[4401],{"type":59,"value":4402},"\u003C!-- ✅ Correct: Add prefix -->\n",{"type":53,"tag":302,"props":4404,"children":4405},{"class":304,"line":342},[4406],{"type":53,"tag":302,"props":4407,"children":4408},{},[4409],{"type":59,"value":4410},"\u003CImageView android:src=\"@drawable\u002Fic_home\" \u002F>\n",{"type":53,"tag":277,"props":4412,"children":4413},{},[],{"type":53,"tag":54,"props":4415,"children":4417},{"id":4416},"_6-build-error-diagnosis-fixes",[4418],{"type":59,"value":4419},"6. Build Error Diagnosis & Fixes",{"type":53,"tag":258,"props":4421,"children":4423},{"id":4422},"_61-common-error-quick-reference",[4424],{"type":59,"value":4425},"6.1 Common Error Quick Reference",{"type":53,"tag":68,"props":4427,"children":4428},{},[4429,4450],{"type":53,"tag":72,"props":4430,"children":4431},{},[4432],{"type":53,"tag":76,"props":4433,"children":4434},{},[4435,4440,4445],{"type":53,"tag":80,"props":4436,"children":4437},{},[4438],{"type":59,"value":4439},"Error Keyword",{"type":53,"tag":80,"props":4441,"children":4442},{},[4443],{"type":59,"value":4444},"Cause",{"type":53,"tag":80,"props":4446,"children":4447},{},[4448],{"type":59,"value":4449},"Fix",{"type":53,"tag":96,"props":4451,"children":4452},{},[4453,4475,4497,4519,4541,4570],{"type":53,"tag":76,"props":4454,"children":4455},{},[4456,4465,4470],{"type":53,"tag":103,"props":4457,"children":4458},{},[4459],{"type":53,"tag":137,"props":4460,"children":4462},{"className":4461},[],[4463],{"type":59,"value":4464},"Unresolved reference",{"type":53,"tag":103,"props":4466,"children":4467},{},[4468],{"type":59,"value":4469},"Missing import or undefined",{"type":53,"tag":103,"props":4471,"children":4472},{},[4473],{"type":59,"value":4474},"Check imports, verify dependencies",{"type":53,"tag":76,"props":4476,"children":4477},{},[4478,4487,4492],{"type":53,"tag":103,"props":4479,"children":4480},{},[4481],{"type":53,"tag":137,"props":4482,"children":4484},{"className":4483},[],[4485],{"type":59,"value":4486},"Type mismatch",{"type":53,"tag":103,"props":4488,"children":4489},{},[4490],{"type":59,"value":4491},"Type incompatibility",{"type":53,"tag":103,"props":4493,"children":4494},{},[4495],{"type":59,"value":4496},"Check parameter types, add conversion",{"type":53,"tag":76,"props":4498,"children":4499},{},[4500,4509,4514],{"type":53,"tag":103,"props":4501,"children":4502},{},[4503],{"type":53,"tag":137,"props":4504,"children":4506},{"className":4505},[],[4507],{"type":59,"value":4508},"Cannot access",{"type":53,"tag":103,"props":4510,"children":4511},{},[4512],{"type":59,"value":4513},"Visibility issue",{"type":53,"tag":103,"props":4515,"children":4516},{},[4517],{"type":59,"value":4518},"Check public\u002Fprivate\u002Finternal",{"type":53,"tag":76,"props":4520,"children":4521},{},[4522,4531,4536],{"type":53,"tag":103,"props":4523,"children":4524},{},[4525],{"type":53,"tag":137,"props":4526,"children":4528},{"className":4527},[],[4529],{"type":59,"value":4530},"@Composable invocations",{"type":53,"tag":103,"props":4532,"children":4533},{},[4534],{"type":59,"value":4535},"Composable context error",{"type":53,"tag":103,"props":4537,"children":4538},{},[4539],{"type":59,"value":4540},"Ensure caller is also @Composable",{"type":53,"tag":76,"props":4542,"children":4543},{},[4544,4553,4558],{"type":53,"tag":103,"props":4545,"children":4546},{},[4547],{"type":53,"tag":137,"props":4548,"children":4550},{"className":4549},[],[4551],{"type":59,"value":4552},"Duplicate class",{"type":53,"tag":103,"props":4554,"children":4555},{},[4556],{"type":59,"value":4557},"Dependency conflict",{"type":53,"tag":103,"props":4559,"children":4560},{},[4561,4562,4568],{"type":59,"value":157},{"type":53,"tag":137,"props":4563,"children":4565},{"className":4564},[],[4566],{"type":59,"value":4567},".\u002Fgradlew dependencies",{"type":59,"value":4569}," to investigate",{"type":53,"tag":76,"props":4571,"children":4572},{},[4573,4582,4587],{"type":53,"tag":103,"props":4574,"children":4575},{},[4576],{"type":53,"tag":137,"props":4577,"children":4579},{"className":4578},[],[4580],{"type":59,"value":4581},"AAPT: error",{"type":53,"tag":103,"props":4583,"children":4584},{},[4585],{"type":59,"value":4586},"Resource file error",{"type":53,"tag":103,"props":4588,"children":4589},{},[4590],{"type":59,"value":4591},"Check XML syntax and resource references",{"type":53,"tag":258,"props":4593,"children":4595},{"id":4594},"_62-fix-best-practices",[4596],{"type":59,"value":4597},"6.2 Fix Best Practices",{"type":53,"tag":4599,"props":4600,"children":4601},"ol",{},[4602,4612,4622,4637,4647],{"type":53,"tag":231,"props":4603,"children":4604},{},[4605,4610],{"type":53,"tag":107,"props":4606,"children":4607},{},[4608],{"type":59,"value":4609},"Read the complete error message first",{"type":59,"value":4611},": Locate file and line number",{"type":53,"tag":231,"props":4613,"children":4614},{},[4615,4620],{"type":53,"tag":107,"props":4616,"children":4617},{},[4618],{"type":59,"value":4619},"Check recent changes",{"type":59,"value":4621},": Problems usually in latest modifications",{"type":53,"tag":231,"props":4623,"children":4624},{},[4625,4630,4631],{"type":53,"tag":107,"props":4626,"children":4627},{},[4628],{"type":59,"value":4629},"Clean Build",{"type":59,"value":986},{"type":53,"tag":137,"props":4632,"children":4634},{"className":4633},[],[4635],{"type":59,"value":4636},".\u002Fgradlew clean assembleDebug",{"type":53,"tag":231,"props":4638,"children":4639},{},[4640,4645],{"type":53,"tag":107,"props":4641,"children":4642},{},[4643],{"type":59,"value":4644},"Check dependency versions",{"type":59,"value":4646},": Version conflicts are common causes",{"type":53,"tag":231,"props":4648,"children":4649},{},[4650,4655],{"type":53,"tag":107,"props":4651,"children":4652},{},[4653],{"type":59,"value":4654},"Refresh dependencies if needed",{"type":59,"value":4656},": Clear cache and rebuild",{"type":53,"tag":258,"props":4658,"children":4660},{"id":4659},"_63-debugging-commands",[4661],{"type":59,"value":4662},"6.3 Debugging Commands",{"type":53,"tag":265,"props":4664,"children":4666},{"className":1020,"code":4665,"language":1022,"meta":273,"style":273},"# Clean and build\n.\u002Fgradlew clean assembleDebug\n\n# View dependency tree (investigate conflicts)\n.\u002Fgradlew :app:dependencies\n\n# View detailed errors\n.\u002Fgradlew assembleDebug --stacktrace\n\n# Refresh dependencies\n.\u002Fgradlew --refresh-dependencies\n",[4667],{"type":53,"tag":137,"props":4668,"children":4669},{"__ignoreMap":273},[4670,4678,4695,4702,4710,4722,4729,4737,4753,4760,4768],{"type":53,"tag":302,"props":4671,"children":4672},{"class":304,"line":305},[4673],{"type":53,"tag":302,"props":4674,"children":4675},{"style":1032},[4676],{"type":59,"value":4677},"# Clean and build\n",{"type":53,"tag":302,"props":4679,"children":4680},{"class":304,"line":314},[4681,4685,4690],{"type":53,"tag":302,"props":4682,"children":4683},{"style":1041},[4684],{"type":59,"value":163},{"type":53,"tag":302,"props":4686,"children":4687},{"style":1046},[4688],{"type":59,"value":4689}," clean",{"type":53,"tag":302,"props":4691,"children":4692},{"style":1046},[4693],{"type":59,"value":4694}," assembleDebug\n",{"type":53,"tag":302,"props":4696,"children":4697},{"class":304,"line":323},[4698],{"type":53,"tag":302,"props":4699,"children":4700},{"emptyLinePlaceholder":336},[4701],{"type":59,"value":339},{"type":53,"tag":302,"props":4703,"children":4704},{"class":304,"line":332},[4705],{"type":53,"tag":302,"props":4706,"children":4707},{"style":1032},[4708],{"type":59,"value":4709},"# View dependency tree (investigate conflicts)\n",{"type":53,"tag":302,"props":4711,"children":4712},{"class":304,"line":342},[4713,4717],{"type":53,"tag":302,"props":4714,"children":4715},{"style":1041},[4716],{"type":59,"value":163},{"type":53,"tag":302,"props":4718,"children":4719},{"style":1046},[4720],{"type":59,"value":4721}," :app:dependencies\n",{"type":53,"tag":302,"props":4723,"children":4724},{"class":304,"line":351},[4725],{"type":53,"tag":302,"props":4726,"children":4727},{"emptyLinePlaceholder":336},[4728],{"type":59,"value":339},{"type":53,"tag":302,"props":4730,"children":4731},{"class":304,"line":360},[4732],{"type":53,"tag":302,"props":4733,"children":4734},{"style":1032},[4735],{"type":59,"value":4736},"# View detailed errors\n",{"type":53,"tag":302,"props":4738,"children":4739},{"class":304,"line":369},[4740,4744,4748],{"type":53,"tag":302,"props":4741,"children":4742},{"style":1041},[4743],{"type":59,"value":163},{"type":53,"tag":302,"props":4745,"children":4746},{"style":1046},[4747],{"type":59,"value":1212},{"type":53,"tag":302,"props":4749,"children":4750},{"style":1046},[4751],{"type":59,"value":4752}," --stacktrace\n",{"type":53,"tag":302,"props":4754,"children":4755},{"class":304,"line":377},[4756],{"type":53,"tag":302,"props":4757,"children":4758},{"emptyLinePlaceholder":336},[4759],{"type":59,"value":339},{"type":53,"tag":302,"props":4761,"children":4762},{"class":304,"line":386},[4763],{"type":53,"tag":302,"props":4764,"children":4765},{"style":1032},[4766],{"type":59,"value":4767},"# Refresh dependencies\n",{"type":53,"tag":302,"props":4769,"children":4770},{"class":304,"line":395},[4771,4775],{"type":53,"tag":302,"props":4772,"children":4773},{"style":1041},[4774],{"type":59,"value":163},{"type":53,"tag":302,"props":4776,"children":4777},{"style":1046},[4778],{"type":59,"value":4779}," --refresh-dependencies\n",{"type":53,"tag":277,"props":4781,"children":4782},{},[],{"type":53,"tag":54,"props":4784,"children":4786},{"id":4785},"_7-material-design-3-guidelines",[4787],{"type":59,"value":4788},"7. Material Design 3 Guidelines",{"type":53,"tag":62,"props":4790,"children":4791},{},[4792],{"type":59,"value":4793},"Review Android UI files for compliance with Material Design 3 Guidelines and Android best practices.",{"type":53,"tag":258,"props":4795,"children":4797},{"id":4796},"design-philosophy",[4798],{"type":59,"value":4799},"Design Philosophy",{"type":53,"tag":4801,"props":4802,"children":4804},"h4",{"id":4803},"m3-core-principles",[4805],{"type":59,"value":4806},"M3 Core Principles",{"type":53,"tag":68,"props":4808,"children":4809},{},[4810,4825],{"type":53,"tag":72,"props":4811,"children":4812},{},[4813],{"type":53,"tag":76,"props":4814,"children":4815},{},[4816,4821],{"type":53,"tag":80,"props":4817,"children":4818},{},[4819],{"type":59,"value":4820},"Principle",{"type":53,"tag":80,"props":4822,"children":4823},{},[4824],{"type":59,"value":2089},{"type":53,"tag":96,"props":4826,"children":4827},{},[4828,4844,4860,4876],{"type":53,"tag":76,"props":4829,"children":4830},{},[4831,4839],{"type":53,"tag":103,"props":4832,"children":4833},{},[4834],{"type":53,"tag":107,"props":4835,"children":4836},{},[4837],{"type":59,"value":4838},"Personal",{"type":53,"tag":103,"props":4840,"children":4841},{},[4842],{"type":59,"value":4843},"Dynamic color based on user preferences and wallpaper",{"type":53,"tag":76,"props":4845,"children":4846},{},[4847,4855],{"type":53,"tag":103,"props":4848,"children":4849},{},[4850],{"type":53,"tag":107,"props":4851,"children":4852},{},[4853],{"type":59,"value":4854},"Adaptive",{"type":53,"tag":103,"props":4856,"children":4857},{},[4858],{"type":59,"value":4859},"Responsive across all screen sizes and form factors",{"type":53,"tag":76,"props":4861,"children":4862},{},[4863,4871],{"type":53,"tag":103,"props":4864,"children":4865},{},[4866],{"type":53,"tag":107,"props":4867,"children":4868},{},[4869],{"type":59,"value":4870},"Expressive",{"type":53,"tag":103,"props":4872,"children":4873},{},[4874],{"type":59,"value":4875},"Bold colors and typography with personality",{"type":53,"tag":76,"props":4877,"children":4878},{},[4879,4887],{"type":53,"tag":103,"props":4880,"children":4881},{},[4882],{"type":53,"tag":107,"props":4883,"children":4884},{},[4885],{"type":59,"value":4886},"Accessible",{"type":53,"tag":103,"props":4888,"children":4889},{},[4890],{"type":59,"value":4891},"Inclusive design for all users",{"type":53,"tag":4801,"props":4893,"children":4895},{"id":4894},"m3-expressive-latest",[4896],{"type":59,"value":4897},"M3 Expressive (Latest)",{"type":53,"tag":62,"props":4899,"children":4900},{},[4901],{"type":59,"value":4902},"The latest evolution adds emotion-driven UX through:",{"type":53,"tag":227,"props":4904,"children":4905},{},[4906,4911,4916,4921,4926],{"type":53,"tag":231,"props":4907,"children":4908},{},[4909],{"type":59,"value":4910},"Vibrant, dynamic colors",{"type":53,"tag":231,"props":4912,"children":4913},{},[4914],{"type":59,"value":4915},"Intuitive motion physics",{"type":53,"tag":231,"props":4917,"children":4918},{},[4919],{"type":59,"value":4920},"Adaptive components",{"type":53,"tag":231,"props":4922,"children":4923},{},[4924],{"type":59,"value":4925},"Flexible typography",{"type":53,"tag":231,"props":4927,"children":4928},{},[4929],{"type":59,"value":4930},"Contrasting shapes (35 new shape options)",{"type":53,"tag":258,"props":4932,"children":4934},{"id":4933},"app-style-selection",[4935],{"type":59,"value":4936},"App Style Selection",{"type":53,"tag":62,"props":4938,"children":4939},{},[4940,4945],{"type":53,"tag":107,"props":4941,"children":4942},{},[4943],{"type":59,"value":4944},"Critical Decision",{"type":59,"value":4946},": Match visual style to app category and target audience.",{"type":53,"tag":68,"props":4948,"children":4949},{},[4950,4971],{"type":53,"tag":72,"props":4951,"children":4952},{},[4953],{"type":53,"tag":76,"props":4954,"children":4955},{},[4956,4961,4966],{"type":53,"tag":80,"props":4957,"children":4958},{},[4959],{"type":59,"value":4960},"App Category",{"type":53,"tag":80,"props":4962,"children":4963},{},[4964],{"type":59,"value":4965},"Visual Style",{"type":53,"tag":80,"props":4967,"children":4968},{},[4969],{"type":59,"value":4970},"Key Characteristics",{"type":53,"tag":96,"props":4972,"children":4973},{},[4974,4992,5010,5028,5046,5064,5081,5099],{"type":53,"tag":76,"props":4975,"children":4976},{},[4977,4982,4987],{"type":53,"tag":103,"props":4978,"children":4979},{},[4980],{"type":59,"value":4981},"Utility\u002FTool",{"type":53,"tag":103,"props":4983,"children":4984},{},[4985],{"type":59,"value":4986},"Minimalist",{"type":53,"tag":103,"props":4988,"children":4989},{},[4990],{"type":59,"value":4991},"Clean, efficient, neutral colors",{"type":53,"tag":76,"props":4993,"children":4994},{},[4995,5000,5005],{"type":53,"tag":103,"props":4996,"children":4997},{},[4998],{"type":59,"value":4999},"Finance\u002FBanking",{"type":53,"tag":103,"props":5001,"children":5002},{},[5003],{"type":59,"value":5004},"Professional Trust",{"type":53,"tag":103,"props":5006,"children":5007},{},[5008],{"type":59,"value":5009},"Conservative colors, security-focused",{"type":53,"tag":76,"props":5011,"children":5012},{},[5013,5018,5023],{"type":53,"tag":103,"props":5014,"children":5015},{},[5016],{"type":59,"value":5017},"Health\u002FWellness",{"type":53,"tag":103,"props":5019,"children":5020},{},[5021],{"type":59,"value":5022},"Calm & Natural",{"type":53,"tag":103,"props":5024,"children":5025},{},[5026],{"type":59,"value":5027},"Soft colors, organic shapes",{"type":53,"tag":76,"props":5029,"children":5030},{},[5031,5036,5041],{"type":53,"tag":103,"props":5032,"children":5033},{},[5034],{"type":59,"value":5035},"Kids (3-5)",{"type":53,"tag":103,"props":5037,"children":5038},{},[5039],{"type":59,"value":5040},"Playful Simple",{"type":53,"tag":103,"props":5042,"children":5043},{},[5044],{"type":59,"value":5045},"Bright colors, large targets (56dp+)",{"type":53,"tag":76,"props":5047,"children":5048},{},[5049,5054,5059],{"type":53,"tag":103,"props":5050,"children":5051},{},[5052],{"type":59,"value":5053},"Kids (6-12)",{"type":53,"tag":103,"props":5055,"children":5056},{},[5057],{"type":59,"value":5058},"Fun & Engaging",{"type":53,"tag":103,"props":5060,"children":5061},{},[5062],{"type":59,"value":5063},"Vibrant, gamified feedback",{"type":53,"tag":76,"props":5065,"children":5066},{},[5067,5072,5076],{"type":53,"tag":103,"props":5068,"children":5069},{},[5070],{"type":59,"value":5071},"Social\u002FEntertainment",{"type":53,"tag":103,"props":5073,"children":5074},{},[5075],{"type":59,"value":4870},{"type":53,"tag":103,"props":5077,"children":5078},{},[5079],{"type":59,"value":5080},"Brand-driven, gesture-rich",{"type":53,"tag":76,"props":5082,"children":5083},{},[5084,5089,5094],{"type":53,"tag":103,"props":5085,"children":5086},{},[5087],{"type":59,"value":5088},"Productivity",{"type":53,"tag":103,"props":5090,"children":5091},{},[5092],{"type":59,"value":5093},"Clean & Focused",{"type":53,"tag":103,"props":5095,"children":5096},{},[5097],{"type":59,"value":5098},"Minimal, high contrast",{"type":53,"tag":76,"props":5100,"children":5101},{},[5102,5107,5112],{"type":53,"tag":103,"props":5103,"children":5104},{},[5105],{"type":59,"value":5106},"E-commerce",{"type":53,"tag":103,"props":5108,"children":5109},{},[5110],{"type":59,"value":5111},"Conversion-focused",{"type":53,"tag":103,"props":5113,"children":5114},{},[5115],{"type":59,"value":5116},"Clear CTAs, scannable",{"type":53,"tag":62,"props":5118,"children":5119},{},[5120,5122,5129],{"type":59,"value":5121},"See ",{"type":53,"tag":5123,"props":5124,"children":5126},"a",{"href":5125},"references\u002Fdesign-style-guide.md",[5127],{"type":59,"value":5128},"Design Style Guide",{"type":59,"value":5130}," for detailed style profiles.",{"type":53,"tag":258,"props":5132,"children":5134},{"id":5133},"quick-reference-key-specifications",[5135],{"type":59,"value":5136},"Quick Reference: Key Specifications",{"type":53,"tag":4801,"props":5138,"children":5140},{"id":5139},"color-contrast-requirements",[5141],{"type":59,"value":5142},"Color Contrast Requirements",{"type":53,"tag":68,"props":5144,"children":5145},{},[5146,5162],{"type":53,"tag":72,"props":5147,"children":5148},{},[5149],{"type":53,"tag":76,"props":5150,"children":5151},{},[5152,5157],{"type":53,"tag":80,"props":5153,"children":5154},{},[5155],{"type":59,"value":5156},"Element",{"type":53,"tag":80,"props":5158,"children":5159},{},[5160],{"type":59,"value":5161},"Minimum Ratio",{"type":53,"tag":96,"props":5163,"children":5164},{},[5165,5181,5197],{"type":53,"tag":76,"props":5166,"children":5167},{},[5168,5173],{"type":53,"tag":103,"props":5169,"children":5170},{},[5171],{"type":59,"value":5172},"Body text",{"type":53,"tag":103,"props":5174,"children":5175},{},[5176],{"type":53,"tag":107,"props":5177,"children":5178},{},[5179],{"type":59,"value":5180},"4.5:1",{"type":53,"tag":76,"props":5182,"children":5183},{},[5184,5189],{"type":53,"tag":103,"props":5185,"children":5186},{},[5187],{"type":59,"value":5188},"Large text (18sp+)",{"type":53,"tag":103,"props":5190,"children":5191},{},[5192],{"type":53,"tag":107,"props":5193,"children":5194},{},[5195],{"type":59,"value":5196},"3:1",{"type":53,"tag":76,"props":5198,"children":5199},{},[5200,5205],{"type":53,"tag":103,"props":5201,"children":5202},{},[5203],{"type":59,"value":5204},"UI components",{"type":53,"tag":103,"props":5206,"children":5207},{},[5208],{"type":53,"tag":107,"props":5209,"children":5210},{},[5211],{"type":59,"value":5196},{"type":53,"tag":4801,"props":5213,"children":5215},{"id":5214},"touch-targets",[5216],{"type":59,"value":5217},"Touch Targets",{"type":53,"tag":68,"props":5219,"children":5220},{},[5221,5235],{"type":53,"tag":72,"props":5222,"children":5223},{},[5224],{"type":53,"tag":76,"props":5225,"children":5226},{},[5227,5231],{"type":53,"tag":80,"props":5228,"children":5229},{},[5230],{"type":59,"value":1630},{"type":53,"tag":80,"props":5232,"children":5233},{},[5234],{"type":59,"value":3681},{"type":53,"tag":96,"props":5236,"children":5237},{},[5238,5251,5264,5277],{"type":53,"tag":76,"props":5239,"children":5240},{},[5241,5246],{"type":53,"tag":103,"props":5242,"children":5243},{},[5244],{"type":59,"value":5245},"Minimum",{"type":53,"tag":103,"props":5247,"children":5248},{},[5249],{"type":59,"value":5250},"48 × 48dp",{"type":53,"tag":76,"props":5252,"children":5253},{},[5254,5259],{"type":53,"tag":103,"props":5255,"children":5256},{},[5257],{"type":59,"value":5258},"Recommended (primary actions)",{"type":53,"tag":103,"props":5260,"children":5261},{},[5262],{"type":59,"value":5263},"56 × 56dp",{"type":53,"tag":76,"props":5265,"children":5266},{},[5267,5272],{"type":53,"tag":103,"props":5268,"children":5269},{},[5270],{"type":59,"value":5271},"Kids apps",{"type":53,"tag":103,"props":5273,"children":5274},{},[5275],{"type":59,"value":5276},"56dp+",{"type":53,"tag":76,"props":5278,"children":5279},{},[5280,5285],{"type":53,"tag":103,"props":5281,"children":5282},{},[5283],{"type":59,"value":5284},"Spacing between targets",{"type":53,"tag":103,"props":5286,"children":5287},{},[5288],{"type":59,"value":5289},"8dp minimum",{"type":53,"tag":4801,"props":5291,"children":5293},{"id":5292},"_8dp-grid-system",[5294],{"type":59,"value":5295},"8dp Grid System",{"type":53,"tag":68,"props":5297,"children":5298},{},[5299,5320],{"type":53,"tag":72,"props":5300,"children":5301},{},[5302],{"type":53,"tag":76,"props":5303,"children":5304},{},[5305,5310,5315],{"type":53,"tag":80,"props":5306,"children":5307},{},[5308],{"type":59,"value":5309},"Token",{"type":53,"tag":80,"props":5311,"children":5312},{},[5313],{"type":59,"value":5314},"Value",{"type":53,"tag":80,"props":5316,"children":5317},{},[5318],{"type":59,"value":5319},"Usage",{"type":53,"tag":96,"props":5321,"children":5322},{},[5323,5341,5359,5377,5395,5413],{"type":53,"tag":76,"props":5324,"children":5325},{},[5326,5331,5336],{"type":53,"tag":103,"props":5327,"children":5328},{},[5329],{"type":59,"value":5330},"xs",{"type":53,"tag":103,"props":5332,"children":5333},{},[5334],{"type":59,"value":5335},"4dp",{"type":53,"tag":103,"props":5337,"children":5338},{},[5339],{"type":59,"value":5340},"Icon padding",{"type":53,"tag":76,"props":5342,"children":5343},{},[5344,5349,5354],{"type":53,"tag":103,"props":5345,"children":5346},{},[5347],{"type":59,"value":5348},"sm",{"type":53,"tag":103,"props":5350,"children":5351},{},[5352],{"type":59,"value":5353},"8dp",{"type":53,"tag":103,"props":5355,"children":5356},{},[5357],{"type":59,"value":5358},"Tight spacing",{"type":53,"tag":76,"props":5360,"children":5361},{},[5362,5367,5372],{"type":53,"tag":103,"props":5363,"children":5364},{},[5365],{"type":59,"value":5366},"md",{"type":53,"tag":103,"props":5368,"children":5369},{},[5370],{"type":59,"value":5371},"16dp",{"type":53,"tag":103,"props":5373,"children":5374},{},[5375],{"type":59,"value":5376},"Default padding",{"type":53,"tag":76,"props":5378,"children":5379},{},[5380,5385,5390],{"type":53,"tag":103,"props":5381,"children":5382},{},[5383],{"type":59,"value":5384},"lg",{"type":53,"tag":103,"props":5386,"children":5387},{},[5388],{"type":59,"value":5389},"24dp",{"type":53,"tag":103,"props":5391,"children":5392},{},[5393],{"type":59,"value":5394},"Section spacing",{"type":53,"tag":76,"props":5396,"children":5397},{},[5398,5403,5408],{"type":53,"tag":103,"props":5399,"children":5400},{},[5401],{"type":59,"value":5402},"xl",{"type":53,"tag":103,"props":5404,"children":5405},{},[5406],{"type":59,"value":5407},"32dp",{"type":53,"tag":103,"props":5409,"children":5410},{},[5411],{"type":59,"value":5412},"Large gaps",{"type":53,"tag":76,"props":5414,"children":5415},{},[5416,5421,5426],{"type":53,"tag":103,"props":5417,"children":5418},{},[5419],{"type":59,"value":5420},"xxl",{"type":53,"tag":103,"props":5422,"children":5423},{},[5424],{"type":59,"value":5425},"48dp",{"type":53,"tag":103,"props":5427,"children":5428},{},[5429],{"type":59,"value":5430},"Screen margins",{"type":53,"tag":4801,"props":5432,"children":5434},{"id":5433},"typography-scale-summary",[5435],{"type":59,"value":5436},"Typography Scale (Summary)",{"type":53,"tag":68,"props":5438,"children":5439},{},[5440,5455],{"type":53,"tag":72,"props":5441,"children":5442},{},[5443],{"type":53,"tag":76,"props":5444,"children":5445},{},[5446,5450],{"type":53,"tag":80,"props":5447,"children":5448},{},[5449],{"type":59,"value":4000},{"type":53,"tag":80,"props":5451,"children":5452},{},[5453],{"type":59,"value":5454},"Sizes",{"type":53,"tag":96,"props":5456,"children":5457},{},[5458,5471,5484,5497,5510],{"type":53,"tag":76,"props":5459,"children":5460},{},[5461,5466],{"type":53,"tag":103,"props":5462,"children":5463},{},[5464],{"type":59,"value":5465},"Display",{"type":53,"tag":103,"props":5467,"children":5468},{},[5469],{"type":59,"value":5470},"57sp, 45sp, 36sp",{"type":53,"tag":76,"props":5472,"children":5473},{},[5474,5479],{"type":53,"tag":103,"props":5475,"children":5476},{},[5477],{"type":59,"value":5478},"Headline",{"type":53,"tag":103,"props":5480,"children":5481},{},[5482],{"type":59,"value":5483},"32sp, 28sp, 24sp",{"type":53,"tag":76,"props":5485,"children":5486},{},[5487,5492],{"type":53,"tag":103,"props":5488,"children":5489},{},[5490],{"type":59,"value":5491},"Title",{"type":53,"tag":103,"props":5493,"children":5494},{},[5495],{"type":59,"value":5496},"22sp, 16sp, 14sp",{"type":53,"tag":76,"props":5498,"children":5499},{},[5500,5505],{"type":53,"tag":103,"props":5501,"children":5502},{},[5503],{"type":59,"value":5504},"Body",{"type":53,"tag":103,"props":5506,"children":5507},{},[5508],{"type":59,"value":5509},"16sp, 14sp, 12sp",{"type":53,"tag":76,"props":5511,"children":5512},{},[5513,5518],{"type":53,"tag":103,"props":5514,"children":5515},{},[5516],{"type":59,"value":5517},"Label",{"type":53,"tag":103,"props":5519,"children":5520},{},[5521],{"type":59,"value":5522},"14sp, 12sp, 11sp",{"type":53,"tag":4801,"props":5524,"children":5526},{"id":5525},"animation-duration",[5527],{"type":59,"value":5528},"Animation Duration",{"type":53,"tag":68,"props":5530,"children":5531},{},[5532,5547],{"type":53,"tag":72,"props":5533,"children":5534},{},[5535],{"type":53,"tag":76,"props":5536,"children":5537},{},[5538,5542],{"type":53,"tag":80,"props":5539,"children":5540},{},[5541],{"type":59,"value":1630},{"type":53,"tag":80,"props":5543,"children":5544},{},[5545],{"type":59,"value":5546},"Duration",{"type":53,"tag":96,"props":5548,"children":5549},{},[5550,5563,5576,5589],{"type":53,"tag":76,"props":5551,"children":5552},{},[5553,5558],{"type":53,"tag":103,"props":5554,"children":5555},{},[5556],{"type":59,"value":5557},"Micro (ripples)",{"type":53,"tag":103,"props":5559,"children":5560},{},[5561],{"type":59,"value":5562},"50-100ms",{"type":53,"tag":76,"props":5564,"children":5565},{},[5566,5571],{"type":53,"tag":103,"props":5567,"children":5568},{},[5569],{"type":59,"value":5570},"Short (simple)",{"type":53,"tag":103,"props":5572,"children":5573},{},[5574],{"type":59,"value":5575},"100-200ms",{"type":53,"tag":76,"props":5577,"children":5578},{},[5579,5584],{"type":53,"tag":103,"props":5580,"children":5581},{},[5582],{"type":59,"value":5583},"Medium (expand\u002Fcollapse)",{"type":53,"tag":103,"props":5585,"children":5586},{},[5587],{"type":59,"value":5588},"200-300ms",{"type":53,"tag":76,"props":5590,"children":5591},{},[5592,5597],{"type":53,"tag":103,"props":5593,"children":5594},{},[5595],{"type":59,"value":5596},"Long (complex)",{"type":53,"tag":103,"props":5598,"children":5599},{},[5600],{"type":59,"value":5601},"300-500ms",{"type":53,"tag":4801,"props":5603,"children":5605},{"id":5604},"component-dimensions",[5606],{"type":59,"value":5607},"Component Dimensions",{"type":53,"tag":68,"props":5609,"children":5610},{},[5611,5632],{"type":53,"tag":72,"props":5612,"children":5613},{},[5614],{"type":53,"tag":76,"props":5615,"children":5616},{},[5617,5622,5627],{"type":53,"tag":80,"props":5618,"children":5619},{},[5620],{"type":59,"value":5621},"Component",{"type":53,"tag":80,"props":5623,"children":5624},{},[5625],{"type":59,"value":5626},"Height",{"type":53,"tag":80,"props":5628,"children":5629},{},[5630],{"type":59,"value":5631},"Min Width",{"type":53,"tag":96,"props":5633,"children":5634},{},[5635,5653,5670,5687,5703],{"type":53,"tag":76,"props":5636,"children":5637},{},[5638,5643,5648],{"type":53,"tag":103,"props":5639,"children":5640},{},[5641],{"type":59,"value":5642},"Button",{"type":53,"tag":103,"props":5644,"children":5645},{},[5646],{"type":59,"value":5647},"40dp",{"type":53,"tag":103,"props":5649,"children":5650},{},[5651],{"type":59,"value":5652},"64dp",{"type":53,"tag":76,"props":5654,"children":5655},{},[5656,5661,5666],{"type":53,"tag":103,"props":5657,"children":5658},{},[5659],{"type":59,"value":5660},"FAB",{"type":53,"tag":103,"props":5662,"children":5663},{},[5664],{"type":59,"value":5665},"56dp",{"type":53,"tag":103,"props":5667,"children":5668},{},[5669],{"type":59,"value":5665},{"type":53,"tag":76,"props":5671,"children":5672},{},[5673,5678,5682],{"type":53,"tag":103,"props":5674,"children":5675},{},[5676],{"type":59,"value":5677},"Text Field",{"type":53,"tag":103,"props":5679,"children":5680},{},[5681],{"type":59,"value":5665},{"type":53,"tag":103,"props":5683,"children":5684},{},[5685],{"type":59,"value":5686},"280dp",{"type":53,"tag":76,"props":5688,"children":5689},{},[5690,5695,5699],{"type":53,"tag":103,"props":5691,"children":5692},{},[5693],{"type":59,"value":5694},"App Bar",{"type":53,"tag":103,"props":5696,"children":5697},{},[5698],{"type":59,"value":5652},{"type":53,"tag":103,"props":5700,"children":5701},{},[5702],{"type":59,"value":3943},{"type":53,"tag":76,"props":5704,"children":5705},{},[5706,5711,5716],{"type":53,"tag":103,"props":5707,"children":5708},{},[5709],{"type":59,"value":5710},"Bottom Nav",{"type":53,"tag":103,"props":5712,"children":5713},{},[5714],{"type":59,"value":5715},"80dp",{"type":53,"tag":103,"props":5717,"children":5718},{},[5719],{"type":59,"value":3943},{"type":53,"tag":258,"props":5721,"children":5723},{"id":5722},"anti-patterns-must-avoid",[5724],{"type":59,"value":5725},"Anti-Patterns (Must Avoid)",{"type":53,"tag":4801,"props":5727,"children":5729},{"id":5728},"ui-anti-patterns",[5730],{"type":59,"value":5731},"UI Anti-Patterns",{"type":53,"tag":227,"props":5733,"children":5734},{},[5735,5740,5745,5750,5755,5760],{"type":53,"tag":231,"props":5736,"children":5737},{},[5738],{"type":59,"value":5739},"More than 5 bottom navigation items",{"type":53,"tag":231,"props":5741,"children":5742},{},[5743],{"type":59,"value":5744},"Multiple FABs on same screen",{"type":53,"tag":231,"props":5746,"children":5747},{},[5748],{"type":59,"value":5749},"Touch targets smaller than 48dp",{"type":53,"tag":231,"props":5751,"children":5752},{},[5753],{"type":59,"value":5754},"Inconsistent spacing (non-8dp multiples)",{"type":53,"tag":231,"props":5756,"children":5757},{},[5758],{"type":59,"value":5759},"Missing dark theme support",{"type":53,"tag":231,"props":5761,"children":5762},{},[5763],{"type":59,"value":5764},"Text on colored backgrounds without contrast check",{"type":53,"tag":4801,"props":5766,"children":5768},{"id":5767},"performance-anti-patterns",[5769],{"type":59,"value":5770},"Performance Anti-Patterns",{"type":53,"tag":227,"props":5772,"children":5773},{},[5774,5779,5784,5789],{"type":53,"tag":231,"props":5775,"children":5776},{},[5777],{"type":59,"value":5778},"Startup time > 2 seconds without progress indicator",{"type":53,"tag":231,"props":5780,"children":5781},{},[5782],{"type":59,"value":5783},"Frame rate \u003C 60 FPS (> 16ms per frame)",{"type":53,"tag":231,"props":5785,"children":5786},{},[5787],{"type":59,"value":5788},"Crash rate > 1.09% (Google Play threshold)",{"type":53,"tag":231,"props":5790,"children":5791},{},[5792],{"type":59,"value":5793},"ANR rate > 0.47% (Google Play threshold)",{"type":53,"tag":4801,"props":5795,"children":5797},{"id":5796},"accessibility-anti-patterns",[5798],{"type":59,"value":5799},"Accessibility Anti-Patterns",{"type":53,"tag":227,"props":5801,"children":5802},{},[5803,5808,5813,5818],{"type":53,"tag":231,"props":5804,"children":5805},{},[5806],{"type":59,"value":5807},"Missing contentDescription on interactive elements",{"type":53,"tag":231,"props":5809,"children":5810},{},[5811],{"type":59,"value":5812},"Element type in labels (e.g., \"Save button\" instead of \"Save\")",{"type":53,"tag":231,"props":5814,"children":5815},{},[5816],{"type":59,"value":5817},"Complex gestures in kids apps",{"type":53,"tag":231,"props":5819,"children":5820},{},[5821],{"type":59,"value":5822},"Text-only buttons for non-readers",{"type":53,"tag":258,"props":5824,"children":5826},{"id":5825},"review-checklist",[5827],{"type":59,"value":5828},"Review Checklist",{"type":53,"tag":227,"props":5830,"children":5833},{"className":5831},[5832],"contains-task-list",[5834,5846,5855,5864,5873,5882,5891,5900],{"type":53,"tag":231,"props":5835,"children":5838},{"className":5836},[5837],"task-list-item",[5839,5844],{"type":53,"tag":5840,"props":5841,"children":5843},"input",{"disabled":336,"type":5842},"checkbox",[],{"type":59,"value":5845}," 8dp spacing grid compliance",{"type":53,"tag":231,"props":5847,"children":5849},{"className":5848},[5837],[5850,5853],{"type":53,"tag":5840,"props":5851,"children":5852},{"disabled":336,"type":5842},[],{"type":59,"value":5854}," 48dp minimum touch targets",{"type":53,"tag":231,"props":5856,"children":5858},{"className":5857},[5837],[5859,5862],{"type":53,"tag":5840,"props":5860,"children":5861},{"disabled":336,"type":5842},[],{"type":59,"value":5863}," Proper typography scale usage",{"type":53,"tag":231,"props":5865,"children":5867},{"className":5866},[5837],[5868,5871],{"type":53,"tag":5840,"props":5869,"children":5870},{"disabled":336,"type":5842},[],{"type":59,"value":5872}," Color contrast compliance (4.5:1+ for text)",{"type":53,"tag":231,"props":5874,"children":5876},{"className":5875},[5837],[5877,5880],{"type":53,"tag":5840,"props":5878,"children":5879},{"disabled":336,"type":5842},[],{"type":59,"value":5881}," Dark theme support",{"type":53,"tag":231,"props":5883,"children":5885},{"className":5884},[5837],[5886,5889],{"type":53,"tag":5840,"props":5887,"children":5888},{"disabled":336,"type":5842},[],{"type":59,"value":5890}," contentDescription on all interactive elements",{"type":53,"tag":231,"props":5892,"children":5894},{"className":5893},[5837],[5895,5898],{"type":53,"tag":5840,"props":5896,"children":5897},{"disabled":336,"type":5842},[],{"type":59,"value":5899}," Startup \u003C 2 seconds or shows progress",{"type":53,"tag":231,"props":5901,"children":5903},{"className":5902},[5837],[5904,5907],{"type":53,"tag":5840,"props":5905,"children":5906},{"disabled":336,"type":5842},[],{"type":59,"value":5908}," Visual style matches app category",{"type":53,"tag":258,"props":5910,"children":5912},{"id":5911},"design-references",[5913],{"type":59,"value":5914},"Design References",{"type":53,"tag":68,"props":5916,"children":5917},{},[5918,5934],{"type":53,"tag":72,"props":5919,"children":5920},{},[5921],{"type":53,"tag":76,"props":5922,"children":5923},{},[5924,5929],{"type":53,"tag":80,"props":5925,"children":5926},{},[5927],{"type":59,"value":5928},"Topic",{"type":53,"tag":80,"props":5930,"children":5931},{},[5932],{"type":59,"value":5933},"Reference",{"type":53,"tag":96,"props":5935,"children":5936},{},[5937,5954,5971,5987,6004,6021,6037,6054],{"type":53,"tag":76,"props":5938,"children":5939},{},[5940,5945],{"type":53,"tag":103,"props":5941,"children":5942},{},[5943],{"type":59,"value":5944},"Colors, Typography, Spacing, Shapes",{"type":53,"tag":103,"props":5946,"children":5947},{},[5948],{"type":53,"tag":5123,"props":5949,"children":5951},{"href":5950},"references\u002Fvisual-design.md",[5952],{"type":59,"value":5953},"Visual Design",{"type":53,"tag":76,"props":5955,"children":5956},{},[5957,5962],{"type":53,"tag":103,"props":5958,"children":5959},{},[5960],{"type":59,"value":5961},"Animation & Transitions",{"type":53,"tag":103,"props":5963,"children":5964},{},[5965],{"type":53,"tag":5123,"props":5966,"children":5968},{"href":5967},"references\u002Fmotion-system.md",[5969],{"type":59,"value":5970},"Motion System",{"type":53,"tag":76,"props":5972,"children":5973},{},[5974,5979],{"type":53,"tag":103,"props":5975,"children":5976},{},[5977],{"type":59,"value":5978},"Accessibility Guidelines",{"type":53,"tag":103,"props":5980,"children":5981},{},[5982],{"type":53,"tag":5123,"props":5983,"children":5985},{"href":5984},"references\u002Faccessibility.md",[5986],{"type":59,"value":21},{"type":53,"tag":76,"props":5988,"children":5989},{},[5990,5995],{"type":53,"tag":103,"props":5991,"children":5992},{},[5993],{"type":59,"value":5994},"Large Screens & Foldables",{"type":53,"tag":103,"props":5996,"children":5997},{},[5998],{"type":53,"tag":5123,"props":5999,"children":6001},{"href":6000},"references\u002Fadaptive-screens.md",[6002],{"type":59,"value":6003},"Adaptive Screens",{"type":53,"tag":76,"props":6005,"children":6006},{},[6007,6012],{"type":53,"tag":103,"props":6008,"children":6009},{},[6010],{"type":59,"value":6011},"Android Vitals & Performance",{"type":53,"tag":103,"props":6013,"children":6014},{},[6015],{"type":53,"tag":5123,"props":6016,"children":6018},{"href":6017},"references\u002Fperformance-stability.md",[6019],{"type":59,"value":6020},"Performance & Stability",{"type":53,"tag":76,"props":6022,"children":6023},{},[6024,6029],{"type":53,"tag":103,"props":6025,"children":6026},{},[6027],{"type":59,"value":6028},"Privacy & Security",{"type":53,"tag":103,"props":6030,"children":6031},{},[6032],{"type":53,"tag":5123,"props":6033,"children":6035},{"href":6034},"references\u002Fprivacy-security.md",[6036],{"type":59,"value":6028},{"type":53,"tag":76,"props":6038,"children":6039},{},[6040,6045],{"type":53,"tag":103,"props":6041,"children":6042},{},[6043],{"type":59,"value":6044},"Audio, Video, Notifications",{"type":53,"tag":103,"props":6046,"children":6047},{},[6048],{"type":53,"tag":5123,"props":6049,"children":6051},{"href":6050},"references\u002Ffunctional-requirements.md",[6052],{"type":59,"value":6053},"Functional Requirements",{"type":53,"tag":76,"props":6055,"children":6056},{},[6057,6062],{"type":53,"tag":103,"props":6058,"children":6059},{},[6060],{"type":59,"value":6061},"App Style by Category",{"type":53,"tag":103,"props":6063,"children":6064},{},[6065],{"type":53,"tag":5123,"props":6066,"children":6067},{"href":5125},[6068],{"type":59,"value":5128},{"type":53,"tag":277,"props":6070,"children":6071},{},[],{"type":53,"tag":54,"props":6073,"children":6075},{"id":6074},"_8-testing",[6076],{"type":59,"value":6077},"8. Testing",{"type":53,"tag":403,"props":6079,"children":6080},{},[6081],{"type":53,"tag":62,"props":6082,"children":6083},{},[6084,6088],{"type":53,"tag":107,"props":6085,"children":6086},{},[6087],{"type":59,"value":413},{"type":59,"value":6089},": Only add test dependencies when the user explicitly asks for testing.",{"type":53,"tag":62,"props":6091,"children":6092},{},[6093],{"type":59,"value":6094},"A well-tested Android app uses layered testing: fast local unit tests for logic, instrumentation tests for UI and integration, and Gradle Managed Devices to run emulators reproducibly on any machine — including CI.",{"type":53,"tag":258,"props":6096,"children":6098},{"id":6097},"_81-test-dependencies",[6099],{"type":59,"value":6100},"8.1 Test Dependencies",{"type":53,"tag":62,"props":6102,"children":6103},{},[6104],{"type":59,"value":6105},"Before adding test dependencies, inspect the project's existing versions to avoid conflicts:",{"type":53,"tag":4599,"props":6107,"children":6108},{},[6109,6122,6134],{"type":53,"tag":231,"props":6110,"children":6111},{},[6112,6114,6120],{"type":59,"value":6113},"Check ",{"type":53,"tag":137,"props":6115,"children":6117},{"className":6116},[],[6118],{"type":59,"value":6119},"gradle\u002Flibs.versions.toml",{"type":59,"value":6121}," — if present, add test deps using the project's version catalog style",{"type":53,"tag":231,"props":6123,"children":6124},{},[6125,6127,6132],{"type":59,"value":6126},"Check existing ",{"type":53,"tag":137,"props":6128,"children":6130},{"className":6129},[],[6131],{"type":59,"value":1370},{"type":59,"value":6133}," for already-pinned dependency versions",{"type":53,"tag":231,"props":6135,"children":6136},{},[6137],{"type":59,"value":6138},"Match version families using the table below",{"type":53,"tag":62,"props":6140,"children":6141},{},[6142,6147],{"type":53,"tag":107,"props":6143,"children":6144},{},[6145],{"type":59,"value":6146},"Version Alignment Rules",{"type":59,"value":225},{"type":53,"tag":68,"props":6149,"children":6150},{},[6151,6172],{"type":53,"tag":72,"props":6152,"children":6153},{},[6154],{"type":53,"tag":76,"props":6155,"children":6156},{},[6157,6162,6167],{"type":53,"tag":80,"props":6158,"children":6159},{},[6160],{"type":59,"value":6161},"Test Dependency",{"type":53,"tag":80,"props":6163,"children":6164},{},[6165],{"type":59,"value":6166},"Must Align With",{"type":53,"tag":80,"props":6168,"children":6169},{},[6170],{"type":59,"value":6171},"How to Check",{"type":53,"tag":96,"props":6173,"children":6174},{},[6175,6213,6256,6284,6326],{"type":53,"tag":76,"props":6176,"children":6177},{},[6178,6187,6200],{"type":53,"tag":103,"props":6179,"children":6180},{},[6181],{"type":53,"tag":137,"props":6182,"children":6184},{"className":6183},[],[6185],{"type":59,"value":6186},"kotlinx-coroutines-test",{"type":53,"tag":103,"props":6188,"children":6189},{},[6190,6192,6198],{"type":59,"value":6191},"Project's ",{"type":53,"tag":137,"props":6193,"children":6195},{"className":6194},[],[6196],{"type":59,"value":6197},"kotlinx-coroutines-core",{"type":59,"value":6199}," version",{"type":53,"tag":103,"props":6201,"children":6202},{},[6203,6205,6211],{"type":59,"value":6204},"Search for ",{"type":53,"tag":137,"props":6206,"children":6208},{"className":6207},[],[6209],{"type":59,"value":6210},"kotlinx-coroutines",{"type":59,"value":6212}," in build files or version catalog",{"type":53,"tag":76,"props":6214,"children":6215},{},[6216,6225,6236],{"type":53,"tag":103,"props":6217,"children":6218},{},[6219],{"type":53,"tag":137,"props":6220,"children":6222},{"className":6221},[],[6223],{"type":59,"value":6224},"compose-ui-test-junit4",{"type":53,"tag":103,"props":6226,"children":6227},{},[6228,6230],{"type":59,"value":6229},"Project's Compose BOM or ",{"type":53,"tag":137,"props":6231,"children":6233},{"className":6232},[],[6234],{"type":59,"value":6235},"compose-compiler",{"type":53,"tag":103,"props":6237,"children":6238},{},[6239,6240,6246,6248,6254],{"type":59,"value":6204},{"type":53,"tag":137,"props":6241,"children":6243},{"className":6242},[],[6244],{"type":59,"value":6245},"compose-bom",{"type":59,"value":6247}," or ",{"type":53,"tag":137,"props":6249,"children":6251},{"className":6250},[],[6252],{"type":59,"value":6253},"compose.compiler",{"type":59,"value":6255}," in build files",{"type":53,"tag":76,"props":6257,"children":6258},{},[6259,6268,6273],{"type":53,"tag":103,"props":6260,"children":6261},{},[6262],{"type":53,"tag":137,"props":6263,"children":6265},{"className":6264},[],[6266],{"type":59,"value":6267},"espresso-*",{"type":53,"tag":103,"props":6269,"children":6270},{},[6271],{"type":59,"value":6272},"All Espresso artifacts must use the same version",{"type":53,"tag":103,"props":6274,"children":6275},{},[6276,6277,6283],{"type":59,"value":6204},{"type":53,"tag":137,"props":6278,"children":6280},{"className":6279},[],[6281],{"type":59,"value":6282},"espresso",{"type":59,"value":6255},{"type":53,"tag":76,"props":6285,"children":6286},{},[6287,6310,6315],{"type":53,"tag":103,"props":6288,"children":6289},{},[6290,6296,6297,6303,6304],{"type":53,"tag":137,"props":6291,"children":6293},{"className":6292},[],[6294],{"type":59,"value":6295},"androidx.test:runner",{"type":59,"value":1002},{"type":53,"tag":137,"props":6298,"children":6300},{"className":6299},[],[6301],{"type":59,"value":6302},"rules",{"type":59,"value":1002},{"type":53,"tag":137,"props":6305,"children":6307},{"className":6306},[],[6308],{"type":59,"value":6309},"ext:junit",{"type":53,"tag":103,"props":6311,"children":6312},{},[6313],{"type":59,"value":6314},"Should use compatible AndroidX Test versions",{"type":53,"tag":103,"props":6316,"children":6317},{},[6318,6319,6325],{"type":59,"value":6204},{"type":53,"tag":137,"props":6320,"children":6322},{"className":6321},[],[6323],{"type":59,"value":6324},"androidx.test",{"type":59,"value":6255},{"type":53,"tag":76,"props":6327,"children":6328},{},[6329,6338,6343],{"type":53,"tag":103,"props":6330,"children":6331},{},[6332],{"type":53,"tag":137,"props":6333,"children":6335},{"className":6334},[],[6336],{"type":59,"value":6337},"mockk",{"type":53,"tag":103,"props":6339,"children":6340},{},[6341],{"type":59,"value":6342},"Must support the project's Kotlin version",{"type":53,"tag":103,"props":6344,"children":6345},{},[6346,6347,6352,6354,6359],{"type":59,"value":6113},{"type":53,"tag":137,"props":6348,"children":6350},{"className":6349},[],[6351],{"type":59,"value":15},{"type":59,"value":6353}," version in root ",{"type":53,"tag":137,"props":6355,"children":6357},{"className":6356},[],[6358],{"type":59,"value":1370},{"type":59,"value":6360}," or version catalog",{"type":53,"tag":62,"props":6362,"children":6363},{},[6364,6369],{"type":53,"tag":107,"props":6365,"children":6366},{},[6367],{"type":59,"value":6368},"Dependencies Reference",{"type":59,"value":6370}," — add only the groups you need:",{"type":53,"tag":265,"props":6372,"children":6374},{"className":440,"code":6373,"language":15,"meta":273,"style":273},"dependencies {\n    \u002F\u002F --- Local unit tests (src\u002Ftest\u002F) ---\n    testImplementation(\"junit:junit:\u003Cversion>\")                          \u002F\u002F 4.13.2+\n    testImplementation(\"org.robolectric:robolectric:\u003Cversion>\")          \u002F\u002F 4.16.1+\n    testImplementation(\"io.mockk:mockk:\u003Cversion>\")                      \u002F\u002F match Kotlin version\n    testImplementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-test:\u003Cversion>\")  \u002F\u002F match coroutines-core\n    testImplementation(\"androidx.arch.core:core-testing:\u003Cversion>\")      \u002F\u002F InstantTaskExecutorRule for LiveData\n    testImplementation(\"app.cash.turbine:turbine:\u003Cversion>\")             \u002F\u002F Flow\u002FStateFlow testing\n\n    \u002F\u002F --- Instrumentation tests (src\u002FandroidTest\u002F) ---\n    androidTestImplementation(\"androidx.test.ext:junit:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test:runner:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test:rules:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.espresso:espresso-core:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.espresso:espresso-contrib:\u003Cversion>\")   \u002F\u002F RecyclerView, Drawer\n    androidTestImplementation(\"androidx.test.espresso:espresso-intents:\u003Cversion>\")   \u002F\u002F Intent verification\n    androidTestImplementation(\"androidx.test.espresso:espresso-idling-resource:\u003Cversion>\")\n    androidTestImplementation(\"androidx.test.uiautomator:uiautomator:\u003Cversion>\")\n\n    \u002F\u002F --- Compose UI tests (only if project uses Compose) ---\n    androidTestImplementation(\"androidx.compose.ui:ui-test-junit4\")      \u002F\u002F version from Compose BOM\n    debugImplementation(\"androidx.compose.ui:ui-test-manifest\")          \u002F\u002F required for createComposeRule\n}\n",[6375],{"type":53,"tag":137,"props":6376,"children":6377},{"__ignoreMap":273},[6378,6385,6393,6401,6409,6417,6425,6433,6441,6448,6456,6464,6472,6480,6488,6496,6504,6512,6520,6527,6535,6543,6551],{"type":53,"tag":302,"props":6379,"children":6380},{"class":304,"line":305},[6381],{"type":53,"tag":302,"props":6382,"children":6383},{},[6384],{"type":59,"value":453},{"type":53,"tag":302,"props":6386,"children":6387},{"class":304,"line":314},[6388],{"type":53,"tag":302,"props":6389,"children":6390},{},[6391],{"type":59,"value":6392},"    \u002F\u002F --- Local unit tests (src\u002Ftest\u002F) ---\n",{"type":53,"tag":302,"props":6394,"children":6395},{"class":304,"line":323},[6396],{"type":53,"tag":302,"props":6397,"children":6398},{},[6399],{"type":59,"value":6400},"    testImplementation(\"junit:junit:\u003Cversion>\")                          \u002F\u002F 4.13.2+\n",{"type":53,"tag":302,"props":6402,"children":6403},{"class":304,"line":332},[6404],{"type":53,"tag":302,"props":6405,"children":6406},{},[6407],{"type":59,"value":6408},"    testImplementation(\"org.robolectric:robolectric:\u003Cversion>\")          \u002F\u002F 4.16.1+\n",{"type":53,"tag":302,"props":6410,"children":6411},{"class":304,"line":342},[6412],{"type":53,"tag":302,"props":6413,"children":6414},{},[6415],{"type":59,"value":6416},"    testImplementation(\"io.mockk:mockk:\u003Cversion>\")                      \u002F\u002F match Kotlin version\n",{"type":53,"tag":302,"props":6418,"children":6419},{"class":304,"line":351},[6420],{"type":53,"tag":302,"props":6421,"children":6422},{},[6423],{"type":59,"value":6424},"    testImplementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-test:\u003Cversion>\")  \u002F\u002F match coroutines-core\n",{"type":53,"tag":302,"props":6426,"children":6427},{"class":304,"line":360},[6428],{"type":53,"tag":302,"props":6429,"children":6430},{},[6431],{"type":59,"value":6432},"    testImplementation(\"androidx.arch.core:core-testing:\u003Cversion>\")      \u002F\u002F InstantTaskExecutorRule for LiveData\n",{"type":53,"tag":302,"props":6434,"children":6435},{"class":304,"line":369},[6436],{"type":53,"tag":302,"props":6437,"children":6438},{},[6439],{"type":59,"value":6440},"    testImplementation(\"app.cash.turbine:turbine:\u003Cversion>\")             \u002F\u002F Flow\u002FStateFlow testing\n",{"type":53,"tag":302,"props":6442,"children":6443},{"class":304,"line":377},[6444],{"type":53,"tag":302,"props":6445,"children":6446},{"emptyLinePlaceholder":336},[6447],{"type":59,"value":339},{"type":53,"tag":302,"props":6449,"children":6450},{"class":304,"line":386},[6451],{"type":53,"tag":302,"props":6452,"children":6453},{},[6454],{"type":59,"value":6455},"    \u002F\u002F --- Instrumentation tests (src\u002FandroidTest\u002F) ---\n",{"type":53,"tag":302,"props":6457,"children":6458},{"class":304,"line":395},[6459],{"type":53,"tag":302,"props":6460,"children":6461},{},[6462],{"type":59,"value":6463},"    androidTestImplementation(\"androidx.test.ext:junit:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6465,"children":6466},{"class":304,"line":642},[6467],{"type":53,"tag":302,"props":6468,"children":6469},{},[6470],{"type":59,"value":6471},"    androidTestImplementation(\"androidx.test:runner:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6473,"children":6474},{"class":304,"line":651},[6475],{"type":53,"tag":302,"props":6476,"children":6477},{},[6478],{"type":59,"value":6479},"    androidTestImplementation(\"androidx.test:rules:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6481,"children":6482},{"class":304,"line":660},[6483],{"type":53,"tag":302,"props":6484,"children":6485},{},[6486],{"type":59,"value":6487},"    androidTestImplementation(\"androidx.test.espresso:espresso-core:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6489,"children":6490},{"class":304,"line":668},[6491],{"type":53,"tag":302,"props":6492,"children":6493},{},[6494],{"type":59,"value":6495},"    androidTestImplementation(\"androidx.test.espresso:espresso-contrib:\u003Cversion>\")   \u002F\u002F RecyclerView, Drawer\n",{"type":53,"tag":302,"props":6497,"children":6498},{"class":304,"line":677},[6499],{"type":53,"tag":302,"props":6500,"children":6501},{},[6502],{"type":59,"value":6503},"    androidTestImplementation(\"androidx.test.espresso:espresso-intents:\u003Cversion>\")   \u002F\u002F Intent verification\n",{"type":53,"tag":302,"props":6505,"children":6506},{"class":304,"line":686},[6507],{"type":53,"tag":302,"props":6508,"children":6509},{},[6510],{"type":59,"value":6511},"    androidTestImplementation(\"androidx.test.espresso:espresso-idling-resource:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6513,"children":6514},{"class":304,"line":695},[6515],{"type":53,"tag":302,"props":6516,"children":6517},{},[6518],{"type":59,"value":6519},"    androidTestImplementation(\"androidx.test.uiautomator:uiautomator:\u003Cversion>\")\n",{"type":53,"tag":302,"props":6521,"children":6522},{"class":304,"line":704},[6523],{"type":53,"tag":302,"props":6524,"children":6525},{"emptyLinePlaceholder":336},[6526],{"type":59,"value":339},{"type":53,"tag":302,"props":6528,"children":6529},{"class":304,"line":713},[6530],{"type":53,"tag":302,"props":6531,"children":6532},{},[6533],{"type":59,"value":6534},"    \u002F\u002F --- Compose UI tests (only if project uses Compose) ---\n",{"type":53,"tag":302,"props":6536,"children":6537},{"class":304,"line":721},[6538],{"type":53,"tag":302,"props":6539,"children":6540},{},[6541],{"type":59,"value":6542},"    androidTestImplementation(\"androidx.compose.ui:ui-test-junit4\")      \u002F\u002F version from Compose BOM\n",{"type":53,"tag":302,"props":6544,"children":6545},{"class":304,"line":730},[6546],{"type":53,"tag":302,"props":6547,"children":6548},{},[6549],{"type":59,"value":6550},"    debugImplementation(\"androidx.compose.ui:ui-test-manifest\")          \u002F\u002F required for createComposeRule\n",{"type":53,"tag":302,"props":6552,"children":6553},{"class":304,"line":739},[6554],{"type":53,"tag":302,"props":6555,"children":6556},{},[6557],{"type":59,"value":525},{"type":53,"tag":403,"props":6559,"children":6560},{},[6561],{"type":53,"tag":62,"props":6562,"children":6563},{},[6564,6568,6570,6576,6577,6583],{"type":53,"tag":107,"props":6565,"children":6566},{},[6567],{"type":59,"value":413},{"type":59,"value":6569},": If the project uses a Compose BOM, ",{"type":53,"tag":137,"props":6571,"children":6573},{"className":6572},[],[6574],{"type":59,"value":6575},"ui-test-junit4",{"type":59,"value":144},{"type":53,"tag":137,"props":6578,"children":6580},{"className":6579},[],[6581],{"type":59,"value":6582},"ui-test-manifest",{"type":59,"value":6584}," don't need explicit versions — the BOM manages them.",{"type":53,"tag":62,"props":6586,"children":6587},{},[6588,6590,6595],{"type":59,"value":6589},"Enable Robolectric resource support in the ",{"type":53,"tag":137,"props":6591,"children":6593},{"className":6592},[],[6594],{"type":59,"value":19},{"type":59,"value":6596}," block:",{"type":53,"tag":265,"props":6598,"children":6600},{"className":440,"code":6599,"language":15,"meta":273,"style":273},"android {\n    testOptions {\n        unitTests.isIncludeAndroidResources = true  \u002F\u002F required for Robolectric\n    }\n}\n",[6601],{"type":53,"tag":137,"props":6602,"children":6603},{"__ignoreMap":273},[6604,6611,6619,6627,6634],{"type":53,"tag":302,"props":6605,"children":6606},{"class":304,"line":305},[6607],{"type":53,"tag":302,"props":6608,"children":6609},{},[6610],{"type":59,"value":560},{"type":53,"tag":302,"props":6612,"children":6613},{"class":304,"line":314},[6614],{"type":53,"tag":302,"props":6615,"children":6616},{},[6617],{"type":59,"value":6618},"    testOptions {\n",{"type":53,"tag":302,"props":6620,"children":6621},{"class":304,"line":323},[6622],{"type":53,"tag":302,"props":6623,"children":6624},{},[6625],{"type":59,"value":6626},"        unitTests.isIncludeAndroidResources = true  \u002F\u002F required for Robolectric\n",{"type":53,"tag":302,"props":6628,"children":6629},{"class":304,"line":332},[6630],{"type":53,"tag":302,"props":6631,"children":6632},{},[6633],{"type":59,"value":864},{"type":53,"tag":302,"props":6635,"children":6636},{"class":304,"line":342},[6637],{"type":53,"tag":302,"props":6638,"children":6639},{},[6640],{"type":59,"value":525},{"type":53,"tag":258,"props":6642,"children":6644},{"id":6643},"_82-testing-by-layer",[6645],{"type":59,"value":6646},"8.2 Testing by Layer",{"type":53,"tag":68,"props":6648,"children":6649},{},[6650,6681],{"type":53,"tag":72,"props":6651,"children":6652},{},[6653],{"type":53,"tag":76,"props":6654,"children":6655},{},[6656,6661,6666,6671,6676],{"type":53,"tag":80,"props":6657,"children":6658},{},[6659],{"type":59,"value":6660},"Layer",{"type":53,"tag":80,"props":6662,"children":6663},{},[6664],{"type":59,"value":6665},"Location",{"type":53,"tag":80,"props":6667,"children":6668},{},[6669],{"type":59,"value":6670},"Runs On",{"type":53,"tag":80,"props":6672,"children":6673},{},[6674],{"type":59,"value":6675},"Speed",{"type":53,"tag":80,"props":6677,"children":6678},{},[6679],{"type":59,"value":6680},"Use For",{"type":53,"tag":96,"props":6682,"children":6683},{},[6684,6716,6747,6777,6809,6838,6867],{"type":53,"tag":76,"props":6685,"children":6686},{},[6687,6692,6701,6706,6711],{"type":53,"tag":103,"props":6688,"children":6689},{},[6690],{"type":59,"value":6691},"Unit (JUnit)",{"type":53,"tag":103,"props":6693,"children":6694},{},[6695],{"type":53,"tag":137,"props":6696,"children":6698},{"className":6697},[],[6699],{"type":59,"value":6700},"src\u002Ftest\u002F",{"type":53,"tag":103,"props":6702,"children":6703},{},[6704],{"type":59,"value":6705},"JVM",{"type":53,"tag":103,"props":6707,"children":6708},{},[6709],{"type":59,"value":6710},"~ms",{"type":53,"tag":103,"props":6712,"children":6713},{},[6714],{"type":59,"value":6715},"ViewModels, repos, mappers, validators",{"type":53,"tag":76,"props":6717,"children":6718},{},[6719,6724,6732,6737,6742],{"type":53,"tag":103,"props":6720,"children":6721},{},[6722],{"type":59,"value":6723},"Unit + Robolectric",{"type":53,"tag":103,"props":6725,"children":6726},{},[6727],{"type":53,"tag":137,"props":6728,"children":6730},{"className":6729},[],[6731],{"type":59,"value":6700},{"type":53,"tag":103,"props":6733,"children":6734},{},[6735],{"type":59,"value":6736},"JVM + simulated Android",{"type":53,"tag":103,"props":6738,"children":6739},{},[6740],{"type":59,"value":6741},"~100ms",{"type":53,"tag":103,"props":6743,"children":6744},{},[6745],{"type":59,"value":6746},"Code needing Context, resources, SharedPrefs",{"type":53,"tag":76,"props":6748,"children":6749},{},[6750,6755,6763,6768,6772],{"type":53,"tag":103,"props":6751,"children":6752},{},[6753],{"type":59,"value":6754},"Compose UI (local)",{"type":53,"tag":103,"props":6756,"children":6757},{},[6758],{"type":53,"tag":137,"props":6759,"children":6761},{"className":6760},[],[6762],{"type":59,"value":6700},{"type":53,"tag":103,"props":6764,"children":6765},{},[6766],{"type":59,"value":6767},"JVM + Robolectric",{"type":53,"tag":103,"props":6769,"children":6770},{},[6771],{"type":59,"value":6741},{"type":53,"tag":103,"props":6773,"children":6774},{},[6775],{"type":59,"value":6776},"Composable rendering & interaction",{"type":53,"tag":76,"props":6778,"children":6779},{},[6780,6785,6794,6799,6804],{"type":53,"tag":103,"props":6781,"children":6782},{},[6783],{"type":59,"value":6784},"Espresso",{"type":53,"tag":103,"props":6786,"children":6787},{},[6788],{"type":53,"tag":137,"props":6789,"children":6791},{"className":6790},[],[6792],{"type":59,"value":6793},"src\u002FandroidTest\u002F",{"type":53,"tag":103,"props":6795,"children":6796},{},[6797],{"type":59,"value":6798},"Device\u002FEmulator",{"type":53,"tag":103,"props":6800,"children":6801},{},[6802],{"type":59,"value":6803},"~seconds",{"type":53,"tag":103,"props":6805,"children":6806},{},[6807],{"type":59,"value":6808},"View-based UI flows, Intents, DB integration",{"type":53,"tag":76,"props":6810,"children":6811},{},[6812,6817,6825,6829,6833],{"type":53,"tag":103,"props":6813,"children":6814},{},[6815],{"type":59,"value":6816},"Compose UI (device)",{"type":53,"tag":103,"props":6818,"children":6819},{},[6820],{"type":53,"tag":137,"props":6821,"children":6823},{"className":6822},[],[6824],{"type":59,"value":6793},{"type":53,"tag":103,"props":6826,"children":6827},{},[6828],{"type":59,"value":6798},{"type":53,"tag":103,"props":6830,"children":6831},{},[6832],{"type":59,"value":6803},{"type":53,"tag":103,"props":6834,"children":6835},{},[6836],{"type":59,"value":6837},"Full Compose UI flows with real rendering",{"type":53,"tag":76,"props":6839,"children":6840},{},[6841,6846,6854,6858,6862],{"type":53,"tag":103,"props":6842,"children":6843},{},[6844],{"type":59,"value":6845},"UI Automator",{"type":53,"tag":103,"props":6847,"children":6848},{},[6849],{"type":53,"tag":137,"props":6850,"children":6852},{"className":6851},[],[6853],{"type":59,"value":6793},{"type":53,"tag":103,"props":6855,"children":6856},{},[6857],{"type":59,"value":6798},{"type":53,"tag":103,"props":6859,"children":6860},{},[6861],{"type":59,"value":6803},{"type":53,"tag":103,"props":6863,"children":6864},{},[6865],{"type":59,"value":6866},"System dialogs, notifications, multi-app",{"type":53,"tag":76,"props":6868,"children":6869},{},[6870,6875,6883,6888,6893],{"type":53,"tag":103,"props":6871,"children":6872},{},[6873],{"type":59,"value":6874},"Managed Device",{"type":53,"tag":103,"props":6876,"children":6877},{},[6878],{"type":53,"tag":137,"props":6879,"children":6881},{"className":6880},[],[6882],{"type":59,"value":6793},{"type":53,"tag":103,"props":6884,"children":6885},{},[6886],{"type":59,"value":6887},"Gradle-managed AVD",{"type":53,"tag":103,"props":6889,"children":6890},{},[6891],{"type":59,"value":6892},"~minutes (first run)",{"type":53,"tag":103,"props":6894,"children":6895},{},[6896],{"type":59,"value":6897},"CI, matrix testing across API levels",{"type":53,"tag":62,"props":6899,"children":6900},{},[6901,6902,6908],{"type":59,"value":5121},{"type":53,"tag":5123,"props":6903,"children":6905},{"href":6904},"references\u002Ftesting.md",[6906],{"type":59,"value":6907},"Testing",{"type":59,"value":6909}," for detailed examples, code patterns, and Gradle Managed Device configuration.",{"type":53,"tag":258,"props":6911,"children":6913},{"id":6912},"_83-testing-commands",[6914],{"type":59,"value":6915},"8.3 Testing Commands",{"type":53,"tag":265,"props":6917,"children":6919},{"className":1020,"code":6918,"language":1022,"meta":273,"style":273},"# Local unit tests (fast, no emulator)\n.\u002Fgradlew test                          # all modules\n.\u002Fgradlew :app:testDebugUnitTest        # app module, debug variant\n\n# Single test class\n.\u002Fgradlew :app:testDebugUnitTest --tests \"com.example.myapp.CounterViewModelTest\"\n\n# Instrumentation tests (requires device or managed device)\n.\u002Fgradlew connectedDebugAndroidTest     # on connected device\n.\u002Fgradlew pixel6Api34DebugAndroidTest   # on managed device\n\n# Both together\n.\u002Fgradlew test connectedDebugAndroidTest\n\n# Test with coverage report (JaCoCo)\n.\u002Fgradlew testDebugUnitTest jacocoTestReport\n",[6920],{"type":53,"tag":137,"props":6921,"children":6922},{"__ignoreMap":273},[6923,6931,6948,6965,6972,6980,7010,7017,7025,7042,7059,7066,7074,7090,7097,7105],{"type":53,"tag":302,"props":6924,"children":6925},{"class":304,"line":305},[6926],{"type":53,"tag":302,"props":6927,"children":6928},{"style":1032},[6929],{"type":59,"value":6930},"# Local unit tests (fast, no emulator)\n",{"type":53,"tag":302,"props":6932,"children":6933},{"class":304,"line":314},[6934,6938,6943],{"type":53,"tag":302,"props":6935,"children":6936},{"style":1041},[6937],{"type":59,"value":163},{"type":53,"tag":302,"props":6939,"children":6940},{"style":1046},[6941],{"type":59,"value":6942}," test",{"type":53,"tag":302,"props":6944,"children":6945},{"style":1032},[6946],{"type":59,"value":6947},"                          # all modules\n",{"type":53,"tag":302,"props":6949,"children":6950},{"class":304,"line":323},[6951,6955,6960],{"type":53,"tag":302,"props":6952,"children":6953},{"style":1041},[6954],{"type":59,"value":163},{"type":53,"tag":302,"props":6956,"children":6957},{"style":1046},[6958],{"type":59,"value":6959}," :app:testDebugUnitTest",{"type":53,"tag":302,"props":6961,"children":6962},{"style":1032},[6963],{"type":59,"value":6964},"        # app module, debug variant\n",{"type":53,"tag":302,"props":6966,"children":6967},{"class":304,"line":332},[6968],{"type":53,"tag":302,"props":6969,"children":6970},{"emptyLinePlaceholder":336},[6971],{"type":59,"value":339},{"type":53,"tag":302,"props":6973,"children":6974},{"class":304,"line":342},[6975],{"type":53,"tag":302,"props":6976,"children":6977},{"style":1032},[6978],{"type":59,"value":6979},"# Single test class\n",{"type":53,"tag":302,"props":6981,"children":6982},{"class":304,"line":351},[6983,6987,6991,6996,7001,7006],{"type":53,"tag":302,"props":6984,"children":6985},{"style":1041},[6986],{"type":59,"value":163},{"type":53,"tag":302,"props":6988,"children":6989},{"style":1046},[6990],{"type":59,"value":6959},{"type":53,"tag":302,"props":6992,"children":6993},{"style":1046},[6994],{"type":59,"value":6995}," --tests",{"type":53,"tag":302,"props":6997,"children":6998},{"style":1057},[6999],{"type":59,"value":7000}," \"",{"type":53,"tag":302,"props":7002,"children":7003},{"style":1046},[7004],{"type":59,"value":7005},"com.example.myapp.CounterViewModelTest",{"type":53,"tag":302,"props":7007,"children":7008},{"style":1057},[7009],{"type":59,"value":1070},{"type":53,"tag":302,"props":7011,"children":7012},{"class":304,"line":360},[7013],{"type":53,"tag":302,"props":7014,"children":7015},{"emptyLinePlaceholder":336},[7016],{"type":59,"value":339},{"type":53,"tag":302,"props":7018,"children":7019},{"class":304,"line":369},[7020],{"type":53,"tag":302,"props":7021,"children":7022},{"style":1032},[7023],{"type":59,"value":7024},"# Instrumentation tests (requires device or managed device)\n",{"type":53,"tag":302,"props":7026,"children":7027},{"class":304,"line":377},[7028,7032,7037],{"type":53,"tag":302,"props":7029,"children":7030},{"style":1041},[7031],{"type":59,"value":163},{"type":53,"tag":302,"props":7033,"children":7034},{"style":1046},[7035],{"type":59,"value":7036}," connectedDebugAndroidTest",{"type":53,"tag":302,"props":7038,"children":7039},{"style":1032},[7040],{"type":59,"value":7041},"     # on connected device\n",{"type":53,"tag":302,"props":7043,"children":7044},{"class":304,"line":386},[7045,7049,7054],{"type":53,"tag":302,"props":7046,"children":7047},{"style":1041},[7048],{"type":59,"value":163},{"type":53,"tag":302,"props":7050,"children":7051},{"style":1046},[7052],{"type":59,"value":7053}," pixel6Api34DebugAndroidTest",{"type":53,"tag":302,"props":7055,"children":7056},{"style":1032},[7057],{"type":59,"value":7058},"   # on managed device\n",{"type":53,"tag":302,"props":7060,"children":7061},{"class":304,"line":395},[7062],{"type":53,"tag":302,"props":7063,"children":7064},{"emptyLinePlaceholder":336},[7065],{"type":59,"value":339},{"type":53,"tag":302,"props":7067,"children":7068},{"class":304,"line":642},[7069],{"type":53,"tag":302,"props":7070,"children":7071},{"style":1032},[7072],{"type":59,"value":7073},"# Both together\n",{"type":53,"tag":302,"props":7075,"children":7076},{"class":304,"line":651},[7077,7081,7085],{"type":53,"tag":302,"props":7078,"children":7079},{"style":1041},[7080],{"type":59,"value":163},{"type":53,"tag":302,"props":7082,"children":7083},{"style":1046},[7084],{"type":59,"value":6942},{"type":53,"tag":302,"props":7086,"children":7087},{"style":1046},[7088],{"type":59,"value":7089}," connectedDebugAndroidTest\n",{"type":53,"tag":302,"props":7091,"children":7092},{"class":304,"line":660},[7093],{"type":53,"tag":302,"props":7094,"children":7095},{"emptyLinePlaceholder":336},[7096],{"type":59,"value":339},{"type":53,"tag":302,"props":7098,"children":7099},{"class":304,"line":668},[7100],{"type":53,"tag":302,"props":7101,"children":7102},{"style":1032},[7103],{"type":59,"value":7104},"# Test with coverage report (JaCoCo)\n",{"type":53,"tag":302,"props":7106,"children":7107},{"class":304,"line":677},[7108,7112,7117],{"type":53,"tag":302,"props":7109,"children":7110},{"style":1041},[7111],{"type":59,"value":163},{"type":53,"tag":302,"props":7113,"children":7114},{"style":1046},[7115],{"type":59,"value":7116}," testDebugUnitTest",{"type":53,"tag":302,"props":7118,"children":7119},{"style":1046},[7120],{"type":59,"value":7121}," jacocoTestReport\n",{"type":53,"tag":4173,"props":7123,"children":7124},{},[7125],{"type":59,"value":7126},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":7128,"total":858},[7129,7137,7153,7172,7187,7207,7225,7243,7258,7274,7293,7303],{"slug":4,"name":4,"fn":5,"description":6,"org":7130,"tags":7131,"stars":29,"repoUrl":30,"updatedAt":31},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7132,7133,7134,7135,7136],{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"name":24,"slug":25,"type":16},{"name":27,"slug":28,"type":16},{"slug":7138,"name":7138,"fn":7139,"description":7140,"org":7141,"tags":7142,"stars":29,"repoUrl":30,"updatedAt":7152},"buddy-sings","generate singing performances for AI companions","Use when user wants their Claude Code pet (\u002Fbuddy) to sing a song. Triggers on any request that combines the concept of their Claude Code buddy, pet, or companion with singing or music. Supports multilingual triggers — match equivalent phrases in any language.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7143,7146,7149],{"name":7144,"slug":7145,"type":16},"Agents","agents",{"name":7147,"slug":7148,"type":16},"Audio","audio",{"name":7150,"slug":7151,"type":16},"Creative","creative","2026-07-13T06:16:35.130644",{"slug":7154,"name":7154,"fn":7155,"description":7156,"org":7157,"tags":7158,"stars":29,"repoUrl":30,"updatedAt":7171},"color-font-skill","select color palettes and font pairings","Choose presentation-ready color palettes and font pairings for PPT\u002Fdesign tasks. Use when users ask for visual theme choices, brand-safe palettes, or font recommendations. Triggers include: 配色, 色板, 字体, color palette, font, PPT配色, 字体搭配.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7159,7162,7165,7168],{"name":7160,"slug":7161,"type":16},"Design","design",{"name":7163,"slug":7164,"type":16},"Presentations","presentations",{"name":7166,"slug":7167,"type":16},"Themes","themes",{"name":7169,"slug":7170,"type":16},"Typography","typography","2026-07-13T06:17:02.785587",{"slug":7173,"name":7173,"fn":7174,"description":7175,"org":7176,"tags":7177,"stars":29,"repoUrl":30,"updatedAt":7186},"design-style-skill","select visual design systems for presentations","Select a consistent visual design system for PPT slides using radius\u002Fspacing style recipes. Use when users ask for overall style direction or component styling consistency. Includes Sharp\u002FSoft\u002FRounded\u002FPill recipes, component mappings, typography\u002Fspacing rules, and mixing guidance. Triggers: 风格, style, radius, spacing, 圆角, 间距, PPT风格, 视觉风格, design style, component style.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7178,7179,7182,7185],{"name":7160,"slug":7161,"type":16},{"name":7180,"slug":7181,"type":16},"Design System","design-system",{"name":7183,"slug":7184,"type":16},"PowerPoint","powerpoint",{"name":7163,"slug":7164,"type":16},"2026-07-13T06:17:10.398389",{"slug":7188,"name":7188,"fn":7189,"description":7190,"org":7191,"tags":7192,"stars":29,"repoUrl":30,"updatedAt":7206},"flutter-dev","build cross-platform apps with Flutter","Flutter cross-platform development guide covering widget patterns, Riverpod\u002FBloc state management, GoRouter navigation, performance optimization, and platform-specific implementations. Includes const optimization, responsive layouts, testing strategies, and DevTools profiling.\nUse when: building Flutter apps, implementing state management (Riverpod\u002FBloc), setting up GoRouter navigation, creating custom widgets, optimizing performance, writing widget tests, cross-platform development.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7193,7196,7199,7200,7203],{"name":7194,"slug":7195,"type":16},"Dart","dart",{"name":7197,"slug":7198,"type":16},"Flutter","flutter",{"name":24,"slug":25,"type":16},{"name":7201,"slug":7202,"type":16},"Performance","performance",{"name":7204,"slug":7205,"type":16},"State Management","state-management","2026-07-13T06:16:36.626679",{"slug":7208,"name":7208,"fn":7209,"description":7210,"org":7211,"tags":7212,"stars":29,"repoUrl":30,"updatedAt":7224},"frontend-dev","build visually striking frontend web pages","Full-stack frontend development combining premium UI design, cinematic animations,\nAI-generated media assets, persuasive copywriting, and visual art. Builds complete,\nvisually striking web pages with real media, advanced motion, and compelling copy.\nUse when: building landing pages, marketing sites, product pages, dashboards,\ngenerating media assets (image\u002Fvideo\u002Faudio\u002Fmusic), writing conversion copy,\ncreating generative art, or implementing cinematic scroll animations.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7213,7216,7217,7218,7221],{"name":7214,"slug":7215,"type":16},"Animation","animation",{"name":7150,"slug":7151,"type":16},{"name":7160,"slug":7161,"type":16},{"name":7219,"slug":7220,"type":16},"Frontend","frontend",{"name":7222,"slug":7223,"type":16},"Web Development","web-development","2026-07-13T06:16:39.108827",{"slug":7226,"name":7226,"fn":7227,"description":7228,"org":7229,"tags":7230,"stars":29,"repoUrl":30,"updatedAt":7242},"fullstack-dev","build full-stack web applications","Full-stack backend architecture and frontend-backend integration guide.\nTRIGGER when: building a full-stack app, creating REST API with frontend, scaffolding backend service,\nbuilding todo app, building CRUD app, building real-time app, building chat app,\nExpress + React, Next.js API, Node.js backend, Python backend, Go backend,\ndesigning service layers, implementing error handling, managing config\u002Fauth,\nsetting up API clients, implementing auth flows, handling file uploads,\nadding real-time features (SSE\u002FWebSocket), hardening for production.\nDO NOT TRIGGER when: pure frontend UI work, pure CSS\u002Fstyling, database schema only.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7231,7234,7235,7238,7241],{"name":7232,"slug":7233,"type":16},"Backend","backend",{"name":7219,"slug":7220,"type":16},{"name":7236,"slug":7237,"type":16},"Full-stack","full-stack",{"name":7239,"slug":7240,"type":16},"REST API","rest-api",{"name":7222,"slug":7223,"type":16},"2026-07-13T06:16:43.219005",{"slug":7244,"name":7244,"fn":7245,"description":7246,"org":7247,"tags":7248,"stars":29,"repoUrl":30,"updatedAt":7257},"gif-sticker-maker","create animated GIF stickers from photos","Convert photos (people, pets, objects, logos) into 4 animated GIF stickers with captions.\nUse when: user wants to create cartoon stickers, GIF expressions, emoji packs, animated avatars,\nor convert photos to Funko Pop \u002F Pop Mart blind box style animations.\nTriggers: sticker, GIF, cartoon, emoji, expression pack, avatar animation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7249,7250,7251,7254],{"name":7214,"slug":7215,"type":16},{"name":7150,"slug":7151,"type":16},{"name":7252,"slug":7253,"type":16},"Images","images",{"name":7255,"slug":7256,"type":16},"Media","media","2026-07-13T06:16:51.74461",{"slug":7259,"name":7259,"fn":7260,"description":7261,"org":7262,"tags":7263,"stars":29,"repoUrl":30,"updatedAt":7273},"ios-application-dev","develop iOS applications with SwiftUI and UIKit","iOS application development guide covering UIKit, SnapKit, and SwiftUI. Includes touch targets, safe areas, navigation patterns, Dynamic Type, Dark Mode, accessibility, collection views, common UI components, and SwiftUI design guidelines. For detailed references on specific topics, see the reference files.\nUse when: developing iOS apps, implementing UI, reviewing iOS code, working with UIKit\u002FSnapKit\u002FSwiftUI layouts, building iPhone interfaces, Swift mobile development, Apple HIG compliance, iOS accessibility implementation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7264,7265,7268,7269,7272],{"name":21,"slug":22,"type":16},{"name":7266,"slug":7267,"type":16},"iOS","ios",{"name":24,"slug":25,"type":16},{"name":7270,"slug":7271,"type":16},"SwiftUI","swiftui",{"name":27,"slug":28,"type":16},"2026-07-13T06:16:55.686092",{"slug":7275,"name":7275,"fn":7276,"description":7277,"org":7278,"tags":7279,"stars":29,"repoUrl":30,"updatedAt":7292},"minimax-docx","create and edit DOCX documents","Professional DOCX document creation, editing, and formatting using OpenXML SDK (.NET). Three pipelines: (A) create new documents from scratch, (B) fill\u002Fedit content in existing documents, (C) apply template formatting with XSD validation gate-check. MUST use this skill whenever the user wants to produce, modify, or format a Word document — including when they say \"write a report\", \"draft a proposal\", \"make a contract\", \"fill in this form\", \"reformat to match this template\", or any task whose final output is a .docx file. Even if the user doesn't mention \"docx\" explicitly, if the task implies a printable\u002Fformal document, use this skill.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7280,7283,7286,7289],{"name":7281,"slug":7282,"type":16},"Documents","documents",{"name":7284,"slug":7285,"type":16},"DOCX","docx",{"name":7287,"slug":7288,"type":16},"Office","office",{"name":7290,"slug":7291,"type":16},"Templates","templates","2026-07-13T06:16:40.461868",{"slug":7294,"name":7294,"fn":7295,"description":7296,"org":7297,"tags":7298,"stars":29,"repoUrl":30,"updatedAt":7302},"minimax-music-gen","generate music and audio tracks","Use when user wants to generate music, songs, or audio tracks. Triggers on any request involving music creation, song writing, lyrics generation, audio production, or covers. Also triggers when user provides lyrics and wants them turned into a song, or describes a mood\u002Fscene and wants background music. Supports multilingual triggers — match equivalent phrases in any language. Do NOT use for music playback of existing files, music theory questions, or music recommendation without generation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7299,7300,7301],{"name":7147,"slug":7148,"type":16},{"name":7150,"slug":7151,"type":16},{"name":7255,"slug":7256,"type":16},"2026-07-13T06:16:50.381758",{"slug":7304,"name":7304,"fn":7305,"description":7306,"org":7307,"tags":7308,"stars":29,"repoUrl":30,"updatedAt":7312},"minimax-music-playlist","generate personalized music playlists","Generate personalized music playlists by analyzing the user's music taste and generation feedback history. Triggers on any request involving playlist generation, music taste profiling, or personalized music recommendations. Supports multilingual triggers — match equivalent phrases in any language.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7309,7310,7311],{"name":7147,"slug":7148,"type":16},{"name":7150,"slug":7151,"type":16},{"name":7255,"slug":7256,"type":16},"2026-07-13T06:16:57.002997",{"items":7314,"total":730},[7315,7323,7329,7336,7343,7351,7359],{"slug":4,"name":4,"fn":5,"description":6,"org":7316,"tags":7317,"stars":29,"repoUrl":30,"updatedAt":31},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7318,7319,7320,7321,7322],{"name":21,"slug":22,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"name":24,"slug":25,"type":16},{"name":27,"slug":28,"type":16},{"slug":7138,"name":7138,"fn":7139,"description":7140,"org":7324,"tags":7325,"stars":29,"repoUrl":30,"updatedAt":7152},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7326,7327,7328],{"name":7144,"slug":7145,"type":16},{"name":7147,"slug":7148,"type":16},{"name":7150,"slug":7151,"type":16},{"slug":7154,"name":7154,"fn":7155,"description":7156,"org":7330,"tags":7331,"stars":29,"repoUrl":30,"updatedAt":7171},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7332,7333,7334,7335],{"name":7160,"slug":7161,"type":16},{"name":7163,"slug":7164,"type":16},{"name":7166,"slug":7167,"type":16},{"name":7169,"slug":7170,"type":16},{"slug":7173,"name":7173,"fn":7174,"description":7175,"org":7337,"tags":7338,"stars":29,"repoUrl":30,"updatedAt":7186},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7339,7340,7341,7342],{"name":7160,"slug":7161,"type":16},{"name":7180,"slug":7181,"type":16},{"name":7183,"slug":7184,"type":16},{"name":7163,"slug":7164,"type":16},{"slug":7188,"name":7188,"fn":7189,"description":7190,"org":7344,"tags":7345,"stars":29,"repoUrl":30,"updatedAt":7206},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7346,7347,7348,7349,7350],{"name":7194,"slug":7195,"type":16},{"name":7197,"slug":7198,"type":16},{"name":24,"slug":25,"type":16},{"name":7201,"slug":7202,"type":16},{"name":7204,"slug":7205,"type":16},{"slug":7208,"name":7208,"fn":7209,"description":7210,"org":7352,"tags":7353,"stars":29,"repoUrl":30,"updatedAt":7224},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7354,7355,7356,7357,7358],{"name":7214,"slug":7215,"type":16},{"name":7150,"slug":7151,"type":16},{"name":7160,"slug":7161,"type":16},{"name":7219,"slug":7220,"type":16},{"name":7222,"slug":7223,"type":16},{"slug":7226,"name":7226,"fn":7227,"description":7228,"org":7360,"tags":7361,"stars":29,"repoUrl":30,"updatedAt":7242},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[7362,7363,7364,7365,7366],{"name":7232,"slug":7233,"type":16},{"name":7219,"slug":7220,"type":16},{"name":7236,"slug":7237,"type":16},{"name":7239,"slug":7240,"type":16},{"name":7222,"slug":7223,"type":16}]