What you'll learn
Coordinate push and local notifications, constrained background jobs, token lifecycle, and reliable notification routing. The lesson turns the APIs into a repeatable engineering workflow instead of a collection of isolated snippets.
By the end of this lesson, you'll be able to:
- Apply Local and push notifications in a production-shaped Flutter feature
- Apply Token lifecycle in a production-shaped Flutter feature
- Apply Permission UX in a production-shaped Flutter feature
- Apply Background constraints in a production-shaped Flutter feature
Core mental model
Connect each API to the decision it supports. Flutter code stays maintainable when state, ownership, lifecycle, and platform boundaries are explicit.
| Concept | What it means | Decision rule |
|---|---|---|
| Token lifecycle | A push delivery token can rotate or become invalid | Associate tokens with installations and update or remove them safely |
| Background constraint | Platforms limit when and how long background code runs | Schedule deferrable idempotent work and persist progress |
| Notification route | A payload identifies an in-app destination | Validate payload data and route through the same declarative navigation contract |
Professional workflow
Work in small vertical slices and keep behavior observable from the first iteration.
- Define the idempotent notification journey boundary: user goal, inputs, visible states, ownership, and expected failures.
- Build the smallest working vertical slice with typed data and explicit dependencies.
- Represent loading, empty, success, and failure behavior where the feature can encounter them.
- Verify logic away from the UI, then exercise the rendered behavior at its public boundary.
- Inspect lifecycle, accessibility, performance, security, and platform behavior before widening the feature.
- Refactor only after behavior is protected by repeatable evidence.
Protect the frame
Guided Flutter lab
Build a focused idempotent notification journey slice
This compact example keeps the important ownership and data-flow decisions visible so the behavior is easy to extend and test.
Uri? notificationDestination(Map<String, Object?> data) {
if (data case {
'type': 'lesson_reminder',
'courseId': final String courseId,
'lessonId': final String lessonId,
}) {
return Uri(
path: '/courses/$courseId/lessons/$lessonId',
queryParameters: const {'source': 'notification'},
);
}
return null;
}
Future<void> handleNotification(Map<String, Object?> data) async {
final destination = notificationDestination(data);
if (destination != null) router.go(destination.toString());
}Production practice
Contract
Define the idempotent notification journey inputs, outputs, owner, lifecycle, visible states, and platform assumptions before selecting APIs or packages.
Verification
Protect pure rules with unit tests and the rendered public contract with widget or integration evidence; include one unavailable or failure case.
Operations
Keep dependencies replaceable, log actionable context without user secrets, and measure user-visible behavior before optimizing.
Common failure mode
Independent workshop
Extend the guided lab into a review-ready idempotent notification journey feature that fits the running course portfolio app.
Your finished workshop must include:
- Local and push notifications
- Token lifecycle
- Permission UX
- Background constraints
- Idempotent jobs
- Automated verification and a short design note
Definition of done
Recap & quick check
Key takeaways
- Token lifecycle: Associate tokens with installations and update or remove them safely
- Background constraint: Schedule deferrable idempotent work and persist progress
- Notification route: Validate payload data and route through the same declarative navigation contract
Quick check
1. Which rule best applies to Token lifecycle?
2. Which rule best applies to Background constraint?
3. Which rule best applies to Notification route?
Next: Scalable Flutter Architecture