{"id":"c2bc6ede-5f6a-46f9-80f3-9e51745c101f","shortId":"GH2SRu","kind":"skill","title":"performance","tagline":"27 Android skills for AI agents (Claude Code, Codex, Cursor). Fixes Supabase auth, Hilt errors, design inconsistency, kapt→ksp, missing UiState states. Reduced my token bills 5×. FitGenZ AI shipped in 18 days.","description":"# Android Performance\r\n\r\n## Rule 1: Compose stability — stop unnecessary recomposition\r\n\r\n```kotlin\r\n// ✅ @Stable for classes Compose can't infer stability\r\n@Stable\r\nclass ItemState(\r\n    val id: String,\r\n    val title: String,\r\n    var isExpanded: Boolean = false   // mutable but tracked\r\n)\r\n\r\n// ✅ @Immutable for guaranteed-immutable data (faster than @Stable)\r\n@Immutable\r\ndata class Item(\r\n    val id: String,\r\n    val title: String,\r\n    val tags: List<String>            // List is not stable by default — @Immutable fixes it\r\n)\r\n\r\n// ✅ Use ImmutableList from kotlinx-collections-immutable for stable lists\r\nimplementation(\"org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7\")\r\n\r\n@Composable\r\nfun ItemList(items: ImmutableList<Item>) {  // ImmutableList is stable, List is not\r\n    LazyColumn {\r\n        items(items, key = { it.id }) { item ->\r\n            ItemCard(item = item)   // won't recompose unless item changes\r\n        }\r\n    }\r\n}\r\n\r\n// ❌ List<Item> parameter causes ItemList to recompose on every parent recomposition\r\n@Composable\r\nfun ItemList(items: List<Item>) { ... }\r\n```\r\n\r\n## Rule 2: derivedStateOf — compute only when dependencies change\r\n\r\n```kotlin\r\n// ✅ derivedStateOf — prevents recomposition when result doesn't change\r\n@Composable\r\nfun ItemList(items: List<Item>) {\r\n    val listState = rememberLazyListState()\r\n\r\n    // Only recomputes when scroll position crosses threshold\r\n    val showScrollToTop by remember {\r\n        derivedStateOf { listState.firstVisibleItemIndex > 3 }\r\n    }\r\n\r\n    // Only recomputes when filter changes, not on every recomposition\r\n    val activeItems by remember(items) {\r\n        derivedStateOf { items.filter { it.isActive } }\r\n    }\r\n\r\n    Box {\r\n        LazyColumn(state = listState) {\r\n            items(activeItems, key = { it.id }) { ItemCard(it) }\r\n        }\r\n        AnimatedVisibility(visible = showScrollToTop, modifier = Modifier.align(Alignment.BottomEnd)) {\r\n            ScrollToTopButton(onClick = { /* scroll to top */ })\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n## Rule 3: Baseline Profiles — fast startup\r\n\r\n```kotlin\r\n// ✅ Generate with Macrobenchmark — significant startup improvement\r\n// benchmark/src/androidTest/java/BaselineProfileGenerator.kt\r\n@RunWith(AndroidJUnit4::class)\r\nclass BaselineProfileGenerator {\r\n    @get:Rule\r\n    val rule = BaselineProfileRule()\r\n\r\n    @Test\r\n    fun generate() {\r\n        rule.collect(packageName = \"com.company.app\") {\r\n            pressHome()\r\n            startActivityAndWait()\r\n            // Navigate through main flows\r\n            device.findObject(By.text(\"Home\")).click()\r\n            device.waitForIdle()\r\n        }\r\n    }\r\n}\r\n\r\n// app/build.gradle.kts\r\ndependencies {\r\n    implementation(libs.profileinstaller)\r\n}\r\n```\r\n\r\n## Rule 4: R8 — enable shrinking in release\r\n\r\n```kotlin\r\n// ✅ build.gradle.kts — release config\r\nbuildTypes {\r\n    release {\r\n        isMinifyEnabled = true       // R8 removes unused code\r\n        isShrinkResources = true     // removes unused resources\r\n        proguardFiles(\r\n            getDefaultProguardFile(\"proguard-android-optimize.txt\"),\r\n            \"proguard-rules.pro\"\r\n        )\r\n    }\r\n}\r\n```\r\n\r\n```pro\r\n# proguard-rules.pro — keep what R8 would remove incorrectly\r\n-keep class com.company.app.data.remote.dto.** { *; }  # keep serialization DTOs\r\n-keepclassmembers class * { @com.google.gson.annotations.SerializedName <fields>; }\r\n# Kotlin\r\n-keep class kotlin.** { *; }\r\n-keepclassmembers class **$WhenMappings { *; }\r\n```\r\n\r\n## Rule 5: Image loading performance\r\n\r\n```kotlin\r\n// ✅ Coil — proper sizing and caching\r\nAsyncImage(\r\n    model = ImageRequest.Builder(LocalContext.current)\r\n        .data(imageUrl)\r\n        .size(Size.ORIGINAL)          // or explicit size: .size(400, 300)\r\n        .crossfade(true)\r\n        .memoryCachePolicy(CachePolicy.ENABLED)\r\n        .diskCachePolicy(CachePolicy.ENABLED)\r\n        .build(),\r\n    contentDescription = null,\r\n    contentScale = ContentScale.Crop,\r\n    modifier = Modifier\r\n        .fillMaxWidth()\r\n        .aspectRatio(16f / 9f)\r\n)\r\n\r\n// ✅ Preload images before they're needed\r\nval imageLoader = LocalContext.current.imageLoader\r\nLaunchedEffect(items) {\r\n    items.take(3).forEach { item ->\r\n        imageLoader.enqueue(\r\n            ImageRequest.Builder(context).data(item.imageUrl).build()\r\n        )\r\n    }\r\n}\r\n```\r\n\r\n## Rule 6: Main thread protection\r\n\r\n```kotlin\r\n// ✅ Trace API — mark expensive operations for profiling\r\nsuspend fun processData(input: List<Item>): List<ProcessedItem> = withContext(Dispatchers.Default) {\r\n    trace(\"processData\") {               // visible in Android Studio profiler\r\n        input.map { processItem(it) }\r\n    }\r\n}\r\n\r\n// ✅ Never block main thread — even for \"fast\" operations\r\n// ❌ This blocks main for DB read:\r\nval item = runBlocking { itemDao.getById(id) }\r\n\r\n// ✅ Suspend from coroutine:\r\nval item = withContext(Dispatchers.IO) { itemDao.getById(id) }\r\n```\r\n\r\n## Common Mistakes\r\n\r\n❌ Passing `List<T>` to Composable — use `ImmutableList<T>` or wrap in `@Immutable` class\r\n❌ Computing in composition — move to `remember {}` or `derivedStateOf {}`\r\n❌ `isMinifyEnabled = false` in release — leaves dead code in APK\r\n❌ Loading full-resolution images — always size images to display size\r\n❌ Running DB queries on Main thread — always `withContext(Dispatchers.IO)`\r\n❌ No baseline profile — first launch is 40-60% slower without it","tags":["performance","android","agent","skills","piyushverma0","agent-skills","ai-agent","antigravity","claude-code","codex","cursor","gemini-cli"],"capabilities":["skill","source-piyushverma0","skill-performance","topic-agent-skills","topic-ai-agent","topic-android","topic-antigravity","topic-claude-code","topic-codex","topic-cursor","topic-gemini-cli","topic-hilt","topic-jetpack-compose","topic-kotlin","topic-material3"],"categories":["android-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/piyushverma0/android-agent-skills/performance","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add piyushverma0/android-agent-skills","source_repo":"https://github.com/piyushverma0/android-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (5,388 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:09:10.450Z","embedding":null,"createdAt":"2026-05-18T13:14:50.165Z","updatedAt":"2026-05-18T19:09:10.450Z","lastSeenAt":"2026-05-18T19:09:10.450Z","tsv":"'-60':511 '0.3.7':116 '1':38 '16f':372 '18':33 '2':159 '27':2 '3':196,236,386 '300':356 '4':281 '40':510 '400':355 '5':28,333 '6':396 '9f':373 'activeitem':207,219 'agent':7 'ai':6,30 'alignment.bottomend':229 'alway':489,501 'android':3,35,420 'androidjunit4':250 'animatedvis':224 'api':402 'apk':483 'app/build.gradle.kts':276 'aspectratio':371 'asyncimag':343 'auth':14 'baselin':237,505 'baselineprofilegener':253 'baselineprofilerul':258 'benchmark/src/androidtest/java/baselineprofilegenerator.kt':248 'bill':27 'block':427,435 'boolean':64 'box':214 'build':363,394 'build.gradle.kts':288 'buildtyp':291 'by.text':272 'cach':342 'cachepolicy.enabled':360,362 'caus':145 'chang':142,165,174,201 'class':47,54,80,251,252,317,323,327,330,466 'claud':8 'click':274 'code':9,298,481 'codex':10 'coil':338 'collect':105,114 'com.company.app':264 'com.company.app.data.remote.dto':318 'com.google.gson.annotations.serializedname':324 'common':454 'compos':39,48,117,153,175,459 'composit':469 'comput':161,467 'config':290 'contentdescript':364 'contentscal':366 'contentscale.crop':367 'context':391 'coroutin':447 'cross':188 'crossfad':357 'cursor':11 'data':74,79,347,392 'day':34 'db':438,496 'dead':480 'default':96 'depend':164,277 'derivedstateof':160,167,194,211,474 'design':17 'device.findobject':271 'device.waitforidle':275 'diskcachepolici':361 'dispatchers.default':415 'dispatchers.io':451,503 'display':493 'doesn':172 'dtos':321 'enabl':283 'error':16 'even':430 'everi':150,204 'expens':404 'explicit':352 'fals':65,476 'fast':239,432 'faster':75 'fillmaxwidth':370 'filter':200 'first':507 'fitgenz':29 'fix':12,98 'flow':270 'foreach':387 'full':486 'full-resolut':485 'fun':118,154,176,260,409 'generat':242,261 'get':254 'getdefaultproguardfil':305 'guarante':72 'guaranteed-immut':71 'hilt':15 'home':273 'id':57,83,444,453 'imag':334,375,488,491 'imageload':381 'imageloader.enqueue':389 'imagerequest.builder':345,390 'imageurl':348 'immut':69,73,78,97,106,115,465 'immutablelist':101,121,122,461 'implement':110,278 'improv':247 'inconsist':18 'incorrect':315 'infer':51 'input':411 'input.map':423 'isexpand':63 'isminifyen':293,475 'isshrinkresourc':299 'it.id':132,221 'it.isactive':213 'item':81,120,129,130,133,135,136,141,156,178,210,218,384,388,441,449 'item.imageurl':393 'itemcard':134,222 'itemdao.getbyid':443,452 'itemlist':119,146,155,177 'items.filter':212 'items.take':385 'itemst':55 'kapt':19 'keep':310,316,319,326 'keepclassmemb':322,329 'key':131,220 'kotlin':44,166,241,287,325,328,337,400 'kotlinx':104,113 'kotlinx-collections-immut':103,112 'ksp':20 'launch':508 'launchedeffect':383 'lazycolumn':128,215 'leav':479 'libs.profileinstaller':279 'list':90,91,109,125,143,157,179,412,413,457 'liststat':181,217 'liststate.firstvisibleitemindex':195 'load':335,484 'localcontext.current':346 'localcontext.current.imageloader':382 'macrobenchmark':244 'main':269,397,428,436,499 'mark':403 'memorycachepolici':359 'miss':21 'mistak':455 'model':344 'modifi':227,368,369 'modifier.align':228 'move':470 'mutabl':66 'navig':267 'need':379 'never':426 'null':365 'onclick':231 'oper':405,433 'org.jetbrains.kotlinx':111 'packagenam':263 'paramet':144 'parent':151 'pass':456 'perform':1,36,336 'posit':187 'preload':374 'presshom':265 'prevent':168 'pro':308 'processdata':410,417 'processitem':424 'profil':238,407,422,506 'proguard-android-optimize.txt':306 'proguard-rules.pro':307,309 'proguardfil':304 'proper':339 'protect':399 'queri':497 'r8':282,295,312 're':378 'read':439 'recompos':139,148 'recomposit':43,152,169,205 'recomput':184,198 'reduc':24 'releas':286,289,292,478 'rememb':193,209,472 'rememberlazylistst':182 'remov':296,301,314 'resolut':487 'resourc':303 'result':171 'rule':37,158,235,255,257,280,332,395 'rule.collect':262 'run':495 'runblock':442 'runwith':249 'scroll':186,232 'scrolltotopbutton':230 'serial':320 'ship':31 'showscrolltotop':191,226 'shrink':284 'signific':245 'size':340,349,353,354,490,494 'size.original':350 'skill':4 'skill-performance' 'slower':512 'source-piyushverma0' 'stabil':40,52 'stabl':45,53,77,94,108,124 'startactivityandwait':266 'startup':240,246 'state':23,216 'stop':41 'string':58,61,84,87 'studio':421 'supabas':13 'suspend':408,445 'tag':89 'test':259 'thread':398,429,500 'threshold':189 'titl':60,86 'token':26 'top':234 'topic-agent-skills' 'topic-ai-agent' 'topic-android' 'topic-antigravity' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-gemini-cli' 'topic-hilt' 'topic-jetpack-compose' 'topic-kotlin' 'topic-material3' 'trace':401,416 'track':68 'true':294,300,358 'uistat':22 'unless':140 'unnecessari':42 'unus':297,302 'use':100,460 'val':56,59,82,85,88,180,190,206,256,380,440,448 'var':62 'visibl':225,418 'whenmap':331 'withcontext':414,450,502 'without':513 'won':137 'would':313 'wrap':463","prices":[{"id":"97c0ee1d-60eb-4447-923a-821ae1429203","listingId":"c2bc6ede-5f6a-46f9-80f3-9e51745c101f","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"piyushverma0","category":"android-agent-skills","install_from":"skills.sh"},"createdAt":"2026-05-18T13:14:50.165Z"}],"sources":[{"listingId":"c2bc6ede-5f6a-46f9-80f3-9e51745c101f","source":"github","sourceId":"piyushverma0/android-agent-skills/performance","sourceUrl":"https://github.com/piyushverma0/android-agent-skills/tree/main/skills/performance","isPrimary":false,"firstSeenAt":"2026-05-18T13:14:50.165Z","lastSeenAt":"2026-05-18T19:09:10.450Z"}],"details":{"listingId":"c2bc6ede-5f6a-46f9-80f3-9e51745c101f","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"piyushverma0","slug":"performance","github":{"repo":"piyushverma0/android-agent-skills","stars":8,"topics":["agent-skills","ai-agent","android","antigravity","claude-code","codex","cursor","gemini-cli","hilt","jetpack-compose","kotlin","material3","open-source","skills","supabase"],"license":"mit","html_url":"https://github.com/piyushverma0/android-agent-skills","pushed_at":"2026-04-27T09:15:31Z","description":"27 Android skills for AI agents (Claude Code, Codex, Cursor). Fixes Supabase auth, Hilt errors, design inconsistency, kapt→ksp, missing UiState states. Reduced my token bills 5×. FitGenZ AI shipped in 18 days.","skill_md_sha":"a271db5c0ab983caeb8d9950f7ca386da5d9ba88","skill_md_path":"skills/performance/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/piyushverma0/android-agent-skills/tree/main/skills/performance"},"layout":"multi","source":"github","category":"android-agent-skills","frontmatter":{},"skills_sh_url":"https://skills.sh/piyushverma0/android-agent-skills/performance"},"updatedAt":"2026-05-18T19:09:10.450Z"}}