其他
在 .NET MAUI 中处理应用生命周期与后台状态保存/恢…
当需要在 .NET MAUI 应用中订阅 Window 生命周期事件、在后台/恢复时保存与恢复状态,或挂接平台原生生命周期回调时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 47/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 50/100 ×0.15
适用场景
在 .NET MAUI 中处理应用生命周通用
解决思路
- 理解四种应用状态:Not Running(进程不存在)、Running(前台接收输入)、Deactivated(可见但失去焦点,如对话框、分屏、通知栏)、Stopped(完全后台、UI 不可见);典型流程为 Not Running → Running → Deactivated → Stopped → Running(恢复)或 Not Running(终止)。
- 订阅 Window 的六个跨平台事件:Created(原生窗口已分配)、Activated(窗口获得输入焦点)、Deactivated(窗口失去焦点,可能仍可见)、Stopped(窗口不再可见)、Resumed(窗口从 Stopped 返回前台)、Destroying(原生窗口正在销毁)。
- 方式一:在 App 类中重写 CreateWindow,调用 base.CreateWindow(activationState) 后为 window 的 Created、Activated、Deactivated、Stopped、Resumed、Destroying 事件附加处理程序,再返回 window。
- 方式二:创建 Window 子类(如 AppWindow),重写 OnActivated、OnStopped、OnResumed、OnDestroying 等虚方法,并在 CreateWindow 中返回该子类实例(如 new AppWindow(new AppShell()))。
- 保存与恢复状态的工作流:1) 识别瞬态状态(草稿文本、滚动位置、表单输入、计时器值);2) 在 OnStopped 中保存——小值用 Preferences,较大状态用文件序列化;3) 在 OnResumed 中读取并应用到视图模型;4) 在 Android 上也在 OnDestroying 中保存,因为返回键可能完全跳过 Stopped;5) 保持处理程序快速,在 1–2 秒内完成,避免 Android ANR 或 iOS 看门狗杀进程。
- Android 平台生命周期映射:Created→OnCreate,Activated→OnResume,Deactivated→OnPause,Stopped→OnStop,Resumed→OnRestart→OnStart→OnResume,Destroying→OnDestroy。
- iOS / Mac Catalyst 平台生命周期映射:Created→WillFinishLaunching/SceneWillConnect(AddiOS 方法 .WillFinishLaunching()/.SceneWillConnect()),Activated→DidBecomeActive(.OnActivated()),Deactivated→WillResignActive(.OnResignActivation()),Stopped→DidEnterBackground(.DidEnterBackground()),Resumed→WillEnterForeground(.WillEnterForeground()),Destroying→WillTerminate(.WillTerminate())。
- 注意 iOS 的 UIKit selector 名与 AddiOS builder 方法名不同:不存在 .DidBecomeActive() 或 .WillResignActive() builder 方法,必须使用 .OnActivated() 和 .OnResignActivation(),否则无法编译。
- Windows (WinUI) 平台生命周期映射:Created→OnLaunched,Activated→Activated(前台),Deactivated→Activated(后台),Stopped→VisibilityChanged(false),Resumed→VisibilityChanged(true),Destroying→Closed。
- 当需要超出 Window 事件范围的平台特定回调时,在 MauiProgram.cs 中使用 builder.ConfigureLifecycleEvents,并用 #if ANDROID / #elif IOS || MACCATALYST / #elif WINDOWS 条件编译分别调用 events.AddAndroid(...)、events.AddiOS(...)、events.AddWindows(...) 挂接原生回调(如 Android 的 OnCreate/OnResume/OnPause/OnStop/OnDestroy,iOS 的 OnActivated/OnResignActivation/DidEnterBackground/WillEnterForeground,Windows 的 OnLaunched/OnActivated/OnClosed)。
- 避免陷阱:Resumed 在首次启动时不触发,初始序列是 Created → Activated,因此每次进入前台都要运行的逻辑应放在 OnActivated 而非 OnResumed。
- 避免陷阱:Deactivated ≠ Stopped,对话框、分屏或下拉通知栏只触发 Deactivated 而不触发 Stopped,不要在 OnDeactivated 中做重量级保存。
- 避免陷阱:Android 返回键会跳过 Stopped,可能直接调用 Destroying,因此关键保存逻辑要同时放在 OnStopped 和 OnDestroying 中。
- 避免陷阱:多窗口应用(iPad、Mac Catalyst、桌面 Windows)中每个 Window 实例独立触发各自的生命周期事件,不要假设存在单一的全局生命周期。
- 避免陷阱:长时间运行的处理程序会导致被杀,Android 约 5 秒 ANR 超时、iOS 后台执行时间有限,生命周期处理程序应保持同步且快速,快速保存用 Preferences 而非数据库写入。
- 避免陷阱:不要使用旧版 Xamarin.Forms 生命周期方法 Application.OnStart()、Application.OnSleep()、Application.OnResume(),它们仅为向后兼容而存在且会绕过 Window 级事件;在 .NET MAUI 中应优先使用 Window 生命周期事件(OnActivated、OnStopped、OnResumed 等)以获得正确的多窗口行为。
适用边界 · 注意事项
- 页面级导航事件应使用 Shell 导航相关指引,而非本技能。
- 启动时注册服务应使用依赖注入相关指引,而非本技能。
- 在生命周期上下文之外调用平台特定 API 应使用平台调用(条件编译与 partial 类)相关指引,而非本技能。