Skip to content

MVI ​

The library follows the MVI (Model-View-Intent) pattern, and the data flow below is the same on the desktop and on mobile. A desktop window adds three ways for its ViewModels to work together — Broadcast, Unicast and View Refresh — through a Container. Mobile has no Container, so the sections from Broadcast Flow to View Refresh Flow apply to the desktop only.

Data Flow ​

Broadcast Flow ​

When multiple ViewModels need to react to the same event, use PulseContainer.broadcast():

Unicast Flow ​

When a child ViewModel needs to notify its parent Container, use PulseViewModel.unicast():

View Refresh Flow ​

Container.refresh() forces the Compose view tree to reconstruct. ViewModel states are preserved; only the Composables are re-created:

Component Responsibilities ​

ComponentResponsibility
PulseStateImmutable snapshot of UI data
PulseActionUser intent — what the user wants to do
PulseEventOne-time side effect — navigation, dialog, snackbar
PulseBroadcastCross-ViewModel notification from Container (desktop)
PulseUnicastChild-to-parent notification from ViewModel (desktop)
PulseViewModelOwns state; handles actions and broadcasts; can emit unicasts
PulseContainerCoordinates ViewModels; enables broadcast, unicast handling, and refresh (desktop)
PulseHostCompose wrapper that propagates container key (desktop)
PulseContentCompose wrapper that observes a ViewModel

Lifecycle ​

TIP

onSetup() runs once, when PulseContent first observes the ViewModel. The ViewModel stays active for as long as its ViewModelStoreOwner lives. A composition restart never repeats setup. Neither does refresh().

Which owner that is decides the ViewModel's lifetime.

  • Created under the host owner, it stays alive for the whole screen
  • Created inside a Navigation 3 destination, it is scoped to that back stack entry: covered by another destination it is kept, and popping the route cancels it

The demo builds every destination the second way. See Navigation 3.

Released under the Apache 2.0 License.