Awesome-android-agent-skills android-viewmodel

Best practices for implementing Android ViewModels, specifically focused on StateFlow for UI state and SharedFlow for one-off events.

install
source · Clone the upstream repo
git clone https://github.com/new-silvermoon/awesome-android-agent-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/new-silvermoon/awesome-android-agent-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.github/skills/architecture/android-viewmodel" ~/.claude/skills/new-silvermoon-awesome-android-agent-skills-android-viewmodel && rm -rf "$T"
manifest: .github/skills/architecture/android-viewmodel/SKILL.md
source content

Android ViewModel & State Management

Instructions

Use

ViewModel
to hold state and business logic. It must outlive configuration changes.

1. UI State (StateFlow)

  • What: Represents the persistent state of the UI (e.g.,
    Loading
    ,
    Success(data)
    ,
    Error
    ).
  • Type:
    StateFlow<UiState>
    .
  • Initialization: Must have an initial value.
  • Exposure: Expose as a read-only
    StateFlow
    backing a private
    MutableStateFlow
    .
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()
    
  • Updates: Update state using
    .update { oldState -> ... }
    for thread safety.

2. One-Off Events (SharedFlow)

  • What: Transient events like "Show Toast", "Navigate to Screen", "Show Snackbar".
  • Type:
    SharedFlow<UiEvent>
    .
  • Configuration: Must use
    replay = 0
    to prevent events from re-triggering on screen rotation.
    private val _uiEvent = MutableSharedFlow<UiEvent>(replay = 0)
    val uiEvent: SharedFlow<UiEvent> = _uiEvent.asSharedFlow()
    
  • Sending: Use
    .emit(event)
    (suspend) or
    .tryEmit(event)
    .

3. Collecting in UI

  • Compose: Use
    collectAsStateWithLifecycle()
    for
    StateFlow
    .
    val state by viewModel.uiState.collectAsStateWithLifecycle()
    
    For
    SharedFlow
    , use
    LaunchedEffect
    with
    LocalLifecycleOwner
    .
  • Views (XML): Use
    repeatOnLifecycle(Lifecycle.State.STARTED)
    within a coroutine.

4. Scope

  • Use
    viewModelScope
    for all coroutines started by the ViewModel.
  • Ideally, specific operations should be delegated to UseCases or Repositories.