Skip to content
Agentmart
Submit a tool

android-clean-presentation-architecture

Defines Android Clean Architecture presentation-layer guidance for Hilt DI, ViewModel, StateFlow uiState, one-shot UI events, and Compose screen wiring.

Skill by chonamdoo

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/chonamdoo-android-clean-presentation-architecture

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Defines Android Clean Architecture presentation-layer guidance for Hilt DI, ViewModel, StateFlow uiState, one-shot UI events, and Compose screen wiring. Use when creating, modifying, or reviewing Android feature presentation code for state-based UI and domain-to-UiModel boundaries.

Use cases: presentations, design

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/android-clean-presentation-architecture

What's inside

Skill name
android-clean-presentation-architecture
Description
Defines Android Clean Architecture presentation-layer guidance for Hilt DI, ViewModel, StateFlow uiState, one-shot UI events, and Compose screen wiring. Use when creating, modifying, or reviewing Android feature presentation code for state-based UI and domain-to-UiModel boundaries.
License
MIT
Instructions
262 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Android Clean Presentation Architecture

Use this skill for Android feature work where presentation code should follow a reusable Clean Architecture pattern.

## Quick start

1. Use this for feature or screen presentation state: Hilt entry wiring, ViewModel state holders, `UiState`/`UiAction`/`UiEvent`, `UiModel` mapping, and stateless Compose rendering.
2. Start by locating the screen state holder and its domain dependencies, then model durable `UiState` before wiring Compose routes/screens.
3. If the task is app-wide common error UI, session expiry, maintenance mode, root navigation reset, or global dialog/snackbar/toast ownership, use `android-appshell-error-handling` instead.

## Do not use for

- AppShell-owned common error hosts, `SessionExpired`/`Maintenance` root flow switching, or Navi3 root back stack resets; use `android-appshell-error-handling`.
- Data, network, or domain implementation design except to enforce presentation boundaries and mapper responsibilities.


## Evidence Basis

- Android Hilt docs define `@HiltAndroidApp`, `@AndroidEntryPoint`, `@HiltViewModel`, Hilt modules, and Jetpack integration.
- Android architecture docs position `ViewModel` as the screen-level state holder.
- Android coroutine/Flow docs support `StateFlow`, `stateIn`, and `SharingStarted` for observable UI state.
- Jetpack Compose state docs support state flowing down and events flowing up, with lifecycle-aware collection in Android UI.
- Android UI layer docs separate screen UI state from UI element state and describe UDF/state holders as the UI state production pipeline.
- Android UI events docs distinguish durable state from transient events and recommend reducing critical one-off events to UI state when delivery matters.
- Compose state hoisting docs require immutable state down and events up from the lowest correct state owner.
- Compose stability docs allow `@Stable` on types whose mutation contract Compose cannot otherwise infer.

## Compose/Kotlin Local Skill Loading

For Android/Compose or Android-targeted Kotlin/KMP implementation or review:
- Load every matching local `compose-*`, `kotlin-*`, `navigation-3`, `edge-to-edge`, `adaptive`, and `testing-setup` `SKILL.md` named by the active Android profile.
- Read the exact paths supplied by the active phase resolver and installed skill index; do not guess another host's installation paths.
- When a required skill is unavailable, apply `code-generation-discipline` **Missing Required Skills**.

## Architecture Rule

Apply the required `clean-architecture-core` **Semantic Layers**, **Dependency
Rule**, **Mapping Boundary**, and **Error Boundary**. Apply the required
`android-clean-architecture` for platform composition and DI.

- Keep Retrofit/API infrastructure at the Android network adapter boundary.
- Do not add `BaseViewModel`, `BaseUiState`, or inherited error hooks for new presentation work. Use explicit helpers and mappers.
- The **Server-Driven Screen Exception** below is the scoped exception to the
  shared abstract state-holder prohibition.

## Presentation Boundaries

Keep route/screen wiring, ViewModels, UI values/actions/events, mapping, and
components in the project's adopted presentation boundary. These responsibilities
do not require a fixed folder tree or one file per concept.

Apply the required core's **Mapping Boundary** to presentation projections.
Follow adopted naming conventions: `UiModel` is a semantic role, not a suffix
whose absence alone fails review.

## DI Rule

Apply the required Android adapter's **Hilt DI** for Application/host annotations,
ViewModel injection, provider/binding choice, and network/data binding ownership.

- Compose obtains ViewModels with `hiltViewModel()` only at the state-holder boundary.

Binding ownership:
- Android platform bindings belong at the app/platform composition boundary.
- Serialization, HTTP clients, and API construction belong at the network adapter boundary.
- Locate those roles in the existing project rather than creating a prescribed DI tree.

Binding rule:
- Put shared app/data/network bindings in `SingletonComponent` only when the instance is app-wide.

Route arguments and startup:
- Use normal `@Inject` with `SavedStateHandle` when the adopted navigation and restoration contract supplies route values there.
- Use Hilt assisted injection when route values need explicit construction-time delivery. Assisted values are not persisted after process death; define restoration separately when required.
- Assisted factories accept only route values. Other dependencies stay normal Hilt injections. Choose by argument lifetime and the actual navigation API, not by the mere presence of a route argument; see [Hilt View Models](https://dagger.dev/hilt/view-model.html).
- ViewModel creation belongs in the route/navigation entry wiring, not inside `Screen`.
- Use AndroidX Startup `Initializer` when the SDK/project adopts that initialization mechanism. If it needs Hilt dependencies, use Hilt `@EntryPoint` and application entry-point access; otherwise preserve the SDK's supported initialization contract.

## ViewModel Rule

ViewModels are screen-level state holders:
- use normal or assisted constructor injection according to the route-argument contract above
- expose immutable screen state through `StateFlow`
- keep mutable state private
- accept user input through named callbacks for simple screens or a typed action handler for branchy screens
- expose transient UI behavior through an event `Flow` only when it cannot be reduced to durable screen state
- convert non-suspending UI callbacks into `viewModelScope.launch`
- do not hold `Context`, `Activity`, `NavController`, `Navigator`, `Router`, launchers, `Intent`, `WebView`, or Compose state objects
- do not call navigation APIs directly. Emit state or event; route/navigation wiring executes navigation.

State patterns:
- For imperative screen state, use private `MutableStateFlow` and public `asStateFlow()`.
- For repository/use-case streams, map domain data into UI state and share one `stateIn` value in the state-holder scope. Choose `SharingStarted` and any stop timeout from the actual collector lifetime, upstream cost, and freshness requirements.
- Use `MutableStateFlow.update { ... }` for copy/update operations.
- Use `combine(...)` when UI state depends on multiple flows.
- Keep paging request ids, selected item ids, and active `Job` handles private inside the ViewModel.
- This portfolio's default initial-loading policy is subscription-driven: use a cold flow shared by `stateIn`, rather than starting screen-state loading from `init`. Preserve an explicitly adopted lifecycle-driven loading contract or a product requirement for user-triggered loading; record the owner, restart/re-subscription behavior, and freshness rule. This is an adopted policy, not the only Android-supported lifecycle.
- `MutableStateFlow` is for ViewModel-owned input and transient transition state. State produced from a repository or use-case stream terminates in `stateIn` instead of being pushed into a manually updated `MutableStateFlow`.

Event patterns:
- Prefer modeling critical results as durable screen state. Reserve transient UI events for navigation, snackbar, toast, permission launcher, browser intent, focus, or haptic behavior.
- A buffered `Channel` with `receiveAsFlow()` is one single-consumer, no-replay option, not a no-loss guarantee: cancellation after receipt can lose an element before processing. Define owner/collector lifetimes, buffering, cancellation, and consumption explicitly; use durable state when loss is unacceptable. See [receiveAsFlow cancellation semantics](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/receive-as-flow.html).
- Do not model fire-once effects as `StateFlow`.
- Prefer explicit `UiEvent` sealed interfaces over raw strings or lambdas from ViewModel to UI.

Coroutine rule:
- `viewModelScope.launch` is valid at the UI-to-state-holder boundary.
- Repositories, data sources, and use cases should expose suspend functions or flows instead of storing arbitrary `CoroutineScope`.
- Cancellation-sensitive work should keep `CancellationException` semantics intact.

## UiState Rule

Use a sealed interface for screen state. Add a stability annotation only under
the verified rules below. Represent every reachable condition explicitly:
not-ready when input is missing; loading; refreshing when distinct from first
load; placeholders with stable identity when skeleton content needs it; empty;
success; error; offline when distinct; and permission-required when access
blocks content. Use the project's names and payloads, not a fixed type scaffold.

`UiState`, `UiAction`, and `UiEvent` roles:

From chonamdoo/agent-flow, MIT.

More from chonamdoo/agent-flow

Signals

Stars
0
Forks
0
Open issues
21
Last commit (this folder)
Oct 21, 2026 (8 days ago)
Last release
Oct 21, 2026 (8 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from chonamdoo

Cite this page

android-clean-presentation-architecture skill. Agent Mart. https://agentmart.dev/skills/chonamdoo-android-clean-presentation-architecture (last updated 2026-10-24)