Code

Create CartScreen.kt — the live total

Now — the screen that observes state. feature/cart/presentation/CartScreen.kt.

  • val state by viewModel.uiState.collectAsStateWithLifecycle() — subscribe to the StateFlow. When the state changes, the screen redraws automatically. WithLifecycle means "stop listening when the screen is in the background" (saving resources).
  • if (state.isEmpty) { ... } — an empty cart gets its own view.
  • LazyColumn { items(state.items) { ... } } — a card per item with the name, price and quantity controls ( / +).
  • Every tap is an event going up: viewModel.onEvent(CartEvent.IncreaseQuantity(...)). The screen computes nothing itself — it only sends events and shows state.
  • At the bottom, Total: €... from state.totalPrice.

This is the beauty of MVI: tap + → event → the ViewModel makes a new state → totalPrice is recomputed → the total on screen updates. Live, with no manual "refresh the total".

Verify. To see the cart working, temporarily add a few items (the menu does this next lesson). For example, from the CartScreen.kt preview or a temporary button, call onEvent(CartEvent.AddItem(pizza)). Then:

Tap "+" on Margherita (€8.50):
  qty: 1 → 2          Total: €8.50 → €17.00   (updates instantly)
Tap "−" down to 0:
  the item drops out of the cart

The total moves with the quantity — in real time, with no extra code.

Tip. The "Pay" button is deliberately left out here — Stripe arrives in lesson 11. For now the cart fully works in memory. Next lesson we connect the screens: the menu's "Add to cart" button will send CartEvent.AddItem, and navigation (Nav3) lets you move menu → cart.