Level 2 · Intermediate Real Apps¶
Goal: build multi-screen apps that load data, remember it, share state cleanly between widgets, and come with tests you trust.
Three ideas carry this level:
- Navigation is state. Imperative
push/popis fine for detours; anything addressable (deep links, the web) should be derived from a location with a router. - Share state by subscription, not by passing it everywhere.
InheritedWidgetis the mechanism; Provider and Riverpod are the ergonomic layers on top, and the skill is subscribing to exactly what each widget needs. - Put I/O behind seams. HTTP clients and storage are injected, so every screen can be tested with fakes — no network, no disk, no device.
Modules¶
- Navigation: push, pop & Returning Results — the route stack, awaiting results,
PopScopefor unsaved changes - Declarative Routing with go_router — nested routes, parameters, auth redirects, shell routes
- Lifting State & InheritedWidget — who rebuilds and why, measured
- Provider & ChangeNotifier —
watch,readandselect, with rebuild counts - Riverpod — Notifier, AsyncNotifier, derived providers, overrides in tests
- Async UI: FutureBuilder & StreamBuilder — snapshot states, retry, and the future-in-build trap
- HTTP & JSON — a typed client with validation, error mapping and
MockClienttests - Local Persistence — shared_preferences, atomic JSON files, schema migration, when to use SQLite
- Testing: Unit, Widget & Golden Tests — table-driven tests, fakes with
Completer, golden images and their failures - Project — A Reading List App — go_router + Riverpod + a storage repository, with a full test suite
What you need before starting¶
- Level 1, or equivalent experience: stateful widgets, layout, forms and lists.
- Comfort with Dart
Futures andStreams (Dart Mastery Path). - For lesson 07, the basics of HTTP and JSON APIs; the REST API Mastery Path covers them.
How the examples were checked¶
Every example was run with Flutter 3.44.8 and Dart 3.12.2 using go_router 18.0.2, provider 6.1.5+1,
flutter_riverpod 3.4.3, http 1.6.0 and shared_preferences 2.5.6. Outputs are the actual print output of
flutter test, with the tool's per-test progress lines removed for readability. Several lessons include first attempts that
failed (a setState that returned a Future, a test expectation that was wrong) because the failures teach as much as the fixes.
What wasn't run
No real network calls were made — HTTP examples use MockClient against a reserved example domain — and platform storage was
replaced by in-memory fakes in tests. Nothing was run on a phone or simulator; lesson 08 and the project say exactly what
that does and doesn't prove.