Keep the UI independent from model providers and network behavior.
1. Repository boundary
Define a small suspend function or Flow interface returning domain results. The ViewModel coordinates the request while the adapter translates provider responses. This allows fake responses in tests and provider changes without rewriting screens.
2. UI state and cancellation
Represent idle, running, success and failure explicitly. A cancelled coroutine should stop collection and release work. Assign request identities so a late response cannot overwrite a newer query.
3. Partial versus final output
Streaming text is provisional. Keep partial display state separate from validated final data. Do not trigger a purchase or persistence operation simply because a token fragment resembles a command.
Worked scenario
Submit note A, cancel, then submit note B. A delayed completion for A must not replace the summary of B.
Apply it
Build a fake adapter with delayed, empty and failed responses. Drive the same Compose screen through every state.
Check your understanding
You can test the ViewModel without a real model or an API key. Explain the decision and show evidence from your implementation or design. If you cannot demonstrate it yet, revisit the relevant section before continuing.