.NET MAUI App Lifecycle
Handle application state transitions correctly in .NET MAUI. This skill covers the cross-platform Window lifecycle events, their platform-native mappings, and patterns for preserving state across backgrounding and resume cycles.
When to Use
- Saving or restoring state when the app backgrounds or resumes
- Subscribing to Window lifecycle events (Created, Activated, Deactivated, Stopped, Resumed, Destroying)
- Hooking into platform-native lifecycle callbacks via
ConfigureLifecycleEvents - Deciding where to place initialization, teardown, or refresh logic
- Understanding the difference between Deactivated and Stopped
When Not to Use
- Page-level navigation events — use Shell navigation guidance instead
- Registering services at startup — use dependency injection guidance instead
- Calling platform-specific APIs outside lifecycle context — use platform invoke guidance instead
Inputs
- The target lifecycle transition (e.g., "save draft when backgrounded", "refresh data on resume")
- Which platforms the developer targets (Android, iOS, Mac Catalyst, Windows)
- Whether the app uses multiple windows (iPad, Mac Catalyst, desktop Windows)
App States
A .NET MAUI app moves through four states:
Typical flow: Not Running → Running → Deactivated → Stopped → Running (resumed) or Not Running (terminated).
Window Lifecycle Events
Microsoft.Maui.Controls.Window exposes six cross-platform events:
Subscribing via CreateWindow
Override CreateWindow in your App class and attach event handlers:
Subscribing via a Custom Window Subclass
Create a Window subclass and override the virtual methods:
Return it from CreateWindow:
Workflow: Save and Restore State on Background
- Identify transient state — draft text, scroll position, form inputs, timer values.
- Save in
OnStopped— usePreferencesfor small values or file serialization for larger state. - Restore in
OnResumed— read back saved values and apply to your view model. - Also save in
OnDestroyingon Android — the back button can skipStoppedentirely. - Keep handlers fast — complete within 1–2 seconds to avoid ANR on Android or watchdog kills on iOS.
Platform Lifecycle Mapping
Android
iOS / Mac Catalyst
⚠️ The UIKit selector names and the
AddiOSbuilder method names differ for activation. There is no.DidBecomeActive()or.WillResignActive()builder method — use.OnActivated()and.OnResignActivation()or the code will not compile.
Windows (WinUI)
Hooking Native Lifecycle Directly
Use ConfigureLifecycleEvents in MauiProgram.cs when you need platform-specific callbacks beyond what Window events provide:
Common Pitfalls
-
Resumed does not fire on first launch. The initial sequence is
Created→Activated. UseOnActivatedfor logic that must run on every foreground entry, notOnResumed. -
Deactivated ≠ Stopped. A dialog, split-screen, or notification pull-down triggers
DeactivatedwithoutStopped. Do not perform heavy saves inOnDeactivated— the app may never actually background. -
Android back button skips Stopped. On Android, pressing back may call
Destroyingdirectly withoutStopped. Place critical save logic in bothOnStoppedandOnDestroying. -
Multi-window apps fire events independently. On iPad, Mac Catalyst, and desktop Windows each
Windowinstance fires its own lifecycle events. Do not assume a single global lifecycle. -
Long-running handlers cause kills. Android enforces a ~5 second ANR timeout; iOS has limited background execution time. Keep lifecycle handlers synchronous and fast — use
Preferencesfor quick saves, not database writes. -
Do not use legacy Xamarin.Forms lifecycle methods.
Application.OnStart(),Application.OnSleep(), andApplication.OnResume()exist for backward compatibility but bypass Window-level events. In .NET MAUI, preferWindowlifecycle events (OnActivated,OnStopped,OnResumed, etc.) for correct multi-window behavior.


