viewmodel-integration

Integrates Hilt ViewModels with Jetpack Compose screens using StateFlow and lifecycle-aware collection.

Updated May 9, 2026
One-click install
npx skills add https://github.com/Bumh3rr/solvyx-app --skill viewmodel-integration-bumh3rr
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: viewmodel-integration
Source: https://github.com/Bumh3rr/solvyx-app/tree/main/.opencode/skill/viewmodel-integration
Command: npx skills add https://github.com/Bumh3rr/solvyx-app --skill viewmodel-integration-bumh3rr

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Connecting ViewModels to Jetpack Compose screens often leads to lifecycle bugs, lost one-shot events, leaked state, and tight coupling between composables and ViewModel types. This Skill provides the exact patterns to wire Hilt ViewModels into Compose screens correctly in the Solvyx project. ## Core Features & Use Cases - Lifecycle-safe state collection: Enforces collectAsStateWithLifecycle over collectAsState, with immutable StateFlow exposure and sealed UiState handling for Loading, Loaded, and Error states. - One-shot events via Channel: Implements navigation, snackbar, and dialog effects through Channel/SharedFlow so events are not lost on rotation, unlike StateFlow-based approaches. - Navigation argument handling: Uses SavedStateHandle to receive nav arguments in the ViewModel and LaunchedEffect(key) to reload data when arguments change. - Use Case: When creating a new detail screen that receives a slug from navigation, apply this Skill to inject the ViewModel with hiltViewModel, read the slug via SavedStateHandle, collect uiState lifecycle-aware, and trigger one-shot navigation events safely. ## Quick Start Apply the viewmodel-integration skill to create a new Compose screen that collects StateFlow with collectAsStateWithLifecycle and emits one-shot events through a Channel.

Frequently Asked Questions about viewmodel-integration

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I connect a Hilt ViewModel to a Jetpack Compose screen?▼

Inject the ViewModel with hiltViewModel() only in the root composable of the screen, passing it as a default parameter. Collect its StateFlow with collectAsStateWithLifecycle and render UI from the resulting state, never passing the ViewModel down to child composables.

What is the difference between collectAsState and collectAsStateWithLifecycle?▼

collectAsStateWithLifecycle stops collection when the lifecycle is not active, preventing wasted work and stale updates, while collectAsState collects regardless of lifecycle state. The lifecycle-runtime-compose library provides collectAsStateWithLifecycle and it should always be preferred in Compose screens.

How do I pass navigation arguments to a ViewModel in Compose?▼

Read the argument in the ViewModel constructor through SavedStateHandle, which Hilt injects automatically. In the composable, use LaunchedEffect(argument) to call a load function so the data reloads whenever the argument changes.

Why are my one-shot events lost when using StateFlow in Compose?▼

StateFlow replays its latest value to new collectors, so events like navigation or snackbars can be re-triggered or lost across rotation. Use a Channel exposed as receiveAsFlow or a SharedFlow for one-shot events instead of StateFlow.

Can I inject a ViewModel into child composables with hiltViewModel?▼

No, hiltViewModel should only be called in the root composable of a screen. Child composables should receive plain state and event callbacks as parameters, keeping them decoupled from the ViewModel type and easier to preview and test.

When should I load data in ViewModel init versus LaunchedEffect?▼

Use init in the ViewModel when the data load does not depend on navigation arguments. Use LaunchedEffect(argument) in the composable when loading depends on a navigation parameter, so the load re-triggers correctly when the argument changes.