AgentStack
SKILL verified MIT Self-run

Android Patterns Advanced

skill-marvinrichter-clarc-android-patterns-advanced · by marvinrichter

Advanced Android/Jetpack Compose patterns — Compose performance optimization (@Stable/@Immutable, derivedStateOf, key in LazyColumn, lambda capture hoisting), Coroutines with injectable dispatchers, and reference rules/skills.

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-marvinrichter-clarc-android-patterns-advanced

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Android Patterns Advanced? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Android Patterns — Advanced

This skill extends android-patterns with performance optimization and reference guide. Load android-patterns first.

When to Activate

  • Debugging unnecessary recomposition in Compose
  • Optimizing LazyColumn with large data sets
  • Implementing offline-first Repository with injectable dispatchers
  • Auditing Compose code for lambda capture issues

Kotlin Coroutines in Android

// Repository: bridge between data sources
class ProductRepositoryImpl @Inject constructor(
    private val api: ProductApi,
    private val dao: ProductDao,
    private val dispatchers: CoroutineDispatchers,
) : ProductRepository {

    override fun getProduct(id: String): Flow> = flow {
        // Emit cached data first (offline-first)
        dao.getById(id)?.let { emit(Result.success(it.toDomain())) }

        // Fetch fresh data
        val result = runCatching { api.getProduct(id) }
        result.onSuccess { dto ->
            dao.upsert(dto.toEntity())
            emit(Result.success(dto.toDomain()))
        }.onFailure { error ->
            emit(Result.failure(error))
        }
    }.flowOn(dispatchers.io)
}

// Dispatcher injection (testable)
interface CoroutineDispatchers {
    val main: CoroutineDispatcher
    val io: CoroutineDispatcher
    val default: CoroutineDispatcher
}

class DefaultDispatchers @Inject constructor() : CoroutineDispatchers {
    override val main = Dispatchers.Main
    override val io = Dispatchers.IO
    override val default = Dispatchers.Default
}

// In tests: inject TestDispatchers
class TestDispatchers(testDispatcher: TestCoroutineDispatcher) : CoroutineDispatchers {
    override val main = testDispatcher
    override val io = testDispatcher
    override val default = testDispatcher
}

Compose Performance

// 1. Use stable types to avoid unnecessary recomposition
@Stable // or @Immutable for deeply immutable types
data class ProductUiModel(
    val id: String,
    val name: String,
    val price: String, // formatted string, not Double
)

// 2. Keys in LazyColumn prevent unnecessary re-compositions on list changes
LazyColumn {
    items(products, key = { it.id }) { product ->
        ProductItem(product = product)
    }
}

// 3. derivedStateOf for expensive computed state
val isScrolledPastThreshold by remember {
    derivedStateOf { listState.firstVisibleItemIndex > 5 }
}

// 4. Avoid unnecessary lambda captures — hoist callbacks
// WRONG: new lambda created on every recomposition
LazyColumn {
    items(products) { product ->
        ProductItem(
            product = product,
            onClick = { viewModel.onProductClick(product.id) }, // new lambda each time!
        )
    }
}

// CORRECT: stable reference
LazyColumn {
    items(products, key = { it.id }) { product ->
        ProductItem(
            product = product,
            onClick = viewModel::onProductClick, // stable method reference
        )
    }
}

Reference Rules and Skills

  • rules/android/coding-style.md — Compose file conventions, StateFlow, no Android imports in ViewModels
  • rules/android/testing.md — Compose testTags, Turbine, Paparazzi
  • rules/android/patterns.md — UDF, Repository Pattern, modularization thresholds
  • Skill: android-testing — Compose UI testing, ViewModel testing, screenshot tests
  • Skill: kotlin-patterns — Sealed classes, coroutines, Flow, extension functions

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.