Skillquality 0.45

performance

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.

Price
free
Protocol
skill
Verified
no

What it does

Android Performance

Rule 1: Compose stability — stop unnecessary recomposition

// ✅ @Stable for classes Compose can't infer stability
@Stable
class ItemState(
    val id: String,
    val title: String,
    var isExpanded: Boolean = false   // mutable but tracked
)

// ✅ @Immutable for guaranteed-immutable data (faster than @Stable)
@Immutable
data class Item(
    val id: String,
    val title: String,
    val tags: List<String>            // List is not stable by default — @Immutable fixes it
)

// ✅ Use ImmutableList from kotlinx-collections-immutable for stable lists
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7")

@Composable
fun ItemList(items: ImmutableList<Item>) {  // ImmutableList is stable, List is not
    LazyColumn {
        items(items, key = { it.id }) { item ->
            ItemCard(item = item)   // won't recompose unless item changes
        }
    }
}

// ❌ List<Item> parameter causes ItemList to recompose on every parent recomposition
@Composable
fun ItemList(items: List<Item>) { ... }

Rule 2: derivedStateOf — compute only when dependencies change

// ✅ derivedStateOf — prevents recomposition when result doesn't change
@Composable
fun ItemList(items: List<Item>) {
    val listState = rememberLazyListState()

    // Only recomputes when scroll position crosses threshold
    val showScrollToTop by remember {
        derivedStateOf { listState.firstVisibleItemIndex > 3 }
    }

    // Only recomputes when filter changes, not on every recomposition
    val activeItems by remember(items) {
        derivedStateOf { items.filter { it.isActive } }
    }

    Box {
        LazyColumn(state = listState) {
            items(activeItems, key = { it.id }) { ItemCard(it) }
        }
        AnimatedVisibility(visible = showScrollToTop, modifier = Modifier.align(Alignment.BottomEnd)) {
            ScrollToTopButton(onClick = { /* scroll to top */ })
        }
    }
}

Rule 3: Baseline Profiles — fast startup

// ✅ Generate with Macrobenchmark — significant startup improvement
// benchmark/src/androidTest/java/BaselineProfileGenerator.kt
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
    @get:Rule
    val rule = BaselineProfileRule()

    @Test
    fun generate() {
        rule.collect(packageName = "com.company.app") {
            pressHome()
            startActivityAndWait()
            // Navigate through main flows
            device.findObject(By.text("Home")).click()
            device.waitForIdle()
        }
    }
}

// app/build.gradle.kts
dependencies {
    implementation(libs.profileinstaller)
}

Rule 4: R8 — enable shrinking in release

// ✅ build.gradle.kts — release config
buildTypes {
    release {
        isMinifyEnabled = true       // R8 removes unused code
        isShrinkResources = true     // removes unused resources
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
        )
    }
}
# proguard-rules.pro — keep what R8 would remove incorrectly
-keep class com.company.app.data.remote.dto.** { *; }  # keep serialization DTOs
-keepclassmembers class * { @com.google.gson.annotations.SerializedName <fields>; }
# Kotlin
-keep class kotlin.** { *; }
-keepclassmembers class **$WhenMappings { *; }

Rule 5: Image loading performance

// ✅ Coil — proper sizing and caching
AsyncImage(
    model = ImageRequest.Builder(LocalContext.current)
        .data(imageUrl)
        .size(Size.ORIGINAL)          // or explicit size: .size(400, 300)
        .crossfade(true)
        .memoryCachePolicy(CachePolicy.ENABLED)
        .diskCachePolicy(CachePolicy.ENABLED)
        .build(),
    contentDescription = null,
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .fillMaxWidth()
        .aspectRatio(16f / 9f)
)

// ✅ Preload images before they're needed
val imageLoader = LocalContext.current.imageLoader
LaunchedEffect(items) {
    items.take(3).forEach { item ->
        imageLoader.enqueue(
            ImageRequest.Builder(context).data(item.imageUrl).build()
        )
    }
}

Rule 6: Main thread protection

// ✅ Trace API — mark expensive operations for profiling
suspend fun processData(input: List<Item>): List<ProcessedItem> = withContext(Dispatchers.Default) {
    trace("processData") {               // visible in Android Studio profiler
        input.map { processItem(it) }
    }
}

// ✅ Never block main thread — even for "fast" operations
// ❌ This blocks main for DB read:
val item = runBlocking { itemDao.getById(id) }

// ✅ Suspend from coroutine:
val item = withContext(Dispatchers.IO) { itemDao.getById(id) }

Common Mistakes

❌ Passing List<T> to Composable — use ImmutableList<T> or wrap in @Immutable class ❌ Computing in composition — move to remember {} or derivedStateOf {}isMinifyEnabled = false in release — leaves dead code in APK ❌ Loading full-resolution images — always size images to display size ❌ Running DB queries on Main thread — always withContext(Dispatchers.IO) ❌ No baseline profile — first launch is 40-60% slower without it

Capabilities

skillsource-piyushverma0skill-performancetopic-agent-skillstopic-ai-agenttopic-androidtopic-antigravitytopic-claude-codetopic-codextopic-cursortopic-gemini-clitopic-hilttopic-jetpack-composetopic-kotlintopic-material3

Install

Installnpx skills add piyushverma0/android-agent-skills
Transportskills-sh
Protocolskill

Quality

0.45/ 1.00

deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 8 github stars · SKILL.md body (5,388 chars)

Provenance

Indexed fromgithub
Enriched2026-05-18 19:09:10Z · deterministic:skill-github:v1 · v1
First seen2026-05-18
Last seen2026-05-18

Agent access