1---2name: mavericks-mvi3description: Use when creating or modifying Mavericks 3.x State, MavericksState, MavericksViewModel, AssistedViewModelFactory, hiltMavericksViewModelFactory, ViewModelModule binding, initial args, Compose mavericksViewModel, collectAsStateWithLifecycle, Fragment MavericksView subscriptions, Async execute, setState, withState, DeliveryMode, uniqueOnly, or one-shot effects4---56# Mavericks MVI Guide78Mavericks screens are rendered from immutable state. Keep state data-only, reducers pure, and side effects in ViewModel methods or UI consumers.910## Quick Reference1112| Task | Use |13|---|---|14| Define screen state | `data class XxxState(...) : MavericksState` |15| Create Hilt VM | `@AssistedInject` + `@Assisted initialState` + `Factory` + `hiltMavericksViewModelFactory()` |16| Register VM | `@Binds @IntoMap @ViewModelKey` in the owning `ViewModelModule` |17| One-shot request | `suspend { repo.call() }.execute { copy(request = it) }` |18| Long-lived Flow to normal state | `flow.setOnEach { value -> copy(value = value) }` |19| Refresh without UI flicker | `.execute(retainValue = State::request) { ... }` |20| Compose VM | `mavericksViewModel()` or `mavericksViewModel(argsFactory = { args })` |21| Compose state | `vm.collectAsStateWithLifecycle(State::prop)` |22| Fragment VM | `by fragmentViewModel()` / `activityViewModel()` / `parentFragmentViewModel()` |23| Fragment state | `vm.onEach(State::prop) { ... }` |24| Fragment one-shot | `vm.onEach(State::effect, deliveryMode = uniqueOnly()) { ... }` |25| Read current state in VM | `withState { state -> ... }` or suspend `awaitState()` |2627## Core Rules2829- State must be immutable, public, data-only, and reducer-safe.30- Hilt Mavericks VMs must use `@AssistedInject`, `@Assisted initialState`, `@AssistedFactory`, and `hiltMavericksViewModelFactory()`.31- Every Hilt Mavericks VM must be bound with `@Binds @IntoMap @ViewModelKey`.32- Use `execute` for finite async work represented by `Async<T>`.33- Use `setOnEach` for long-lived Flows that map directly to ordinary State fields.34- Use Mavericks lifecycle-aware Compose collection: `com.airbnb.mvrx.compose.collectAsStateWithLifecycle`.35- `DeliveryMode` is only for `MavericksView` subscriptions, not ViewModel `onEach` and not Compose.36- Effects are a project pattern on top of State; nullable single effects are not queues.3738## Read Only What You Need3940- State fields, immutability, args, and `@PersistState`: [references/state.md](references/state.md)41- ViewModel template, `execute`, `setOnEach`, `setState`, `withState`: [references/viewmodel-execute.md](references/viewmodel-execute.md)42- Hilt component and map binding: [references/hilt.md](references/hilt.md)43- Compose, Fragment, `MavericksView`, `DeliveryMode`, scopes: [references/observing-ui.md](references/observing-ui.md)44- Nullable effects, effect queues, consumption rules: [references/effects.md](references/effects.md)45- `Async<T>` states and rendering patterns: [references/async.md](references/async.md)46- Mavericks ViewModel testing: [references/testing.md](references/testing.md)4748## Common Pitfalls4950| Pitfall | Fix |51|---|---|52| Missing State defaults with no args path | Add defaults or initialize through args/`initialState()` |53| Mutable State field | Use immutable/read-only types and copy on update |54| Storing derived values | Use computed properties |55| Reading immediately after `setState` | Use reducer state, `withState`, or `awaitState()` |56| Heavy work inside reducer | Move work before `setState` or into `execute(dispatcher)` |57| Long action inside VM `onEach` gets cancelled | `onEach` uses `collectLatest`; move long work elsewhere |58| Flow wrapped in `execute` when no `Async` is needed | Use `setOnEach` |59| UI flickers during refresh | Use `retainValue` |60| Rendering state with `uniqueOnly()` | Use default delivery mode |61| Compose using legacy `collectAsState` | Use Mavericks `collectAsStateWithLifecycle` |62| Required Compose args omitted | Use `mavericksViewModel(argsFactory = { args })` |63| Effect fires twice after Fragment restart | Use `uniqueOnly()` and clear after handling |64| Multiple effects lost | Use a list/queue or redesign event semantics |65| Hilt VM creation crashes | Check `@AssistedFactory`, companion factory, and ViewModelModule binding |