MAUI默认无页面级缓存,需通过Shell的CacheNavigation属性、手动维护页面实例或状态持久化实现缓存效果;推荐优先使用CacheNavigation,其次分离UI与数据状态,避免缓存含实时资源或多参数差异的页面。

MAUI 默认不提供页面级缓存机制,页面每次导航都会新建实例,导致重复初始化、状态丢失、性能浪费。要实现类似“页面缓存”效果(即返回时不重建、保留 UI 状态),需手动干预导航生命周期和页面实例管理。
用 Shell 的 CacheNavigation 属性(推荐)
MAUI 6+ 在 Shell 中引入了 CacheNavigation 属性,开启后 Shell 会复用已加载的页面实例而非每次都新建:
- 在 AppShell.xaml 中设置:
- 确保目标页面使用 Shell 路由注册(如
Routing.RegisterRoute("detail", typeof(DetailPage));) - 通过
Shell.GoToAsync("detail")导航时,若该页面已存在且未被释放,Shell 会直接显示缓存实例,OnAppearing仍会触发,但构造函数不会重复执行 - 注意:缓存仅对 Shell 管理的页面生效;页面仍可能被系统回收(如内存紧张),不能完全替代状态持久化
手动维护页面实例(适用于非 Shell 或精细控制)
适合需要完全控制生命周期或使用 NavigationPage 的场景:
- 在 ViewModel 或服务中持有页面实例引用(如
private static DetailPage? _cachedDetail;) - 首次导航时创建并缓存:
_cachedDetail ??= new DetailPage(); - 后续导航改用
Navigation.PushAsync(_cachedDetail)(需确保页面未被弹出过) - 注意:需监听页面卸载事件(如重写
OnDisappearing),必要时清理引用,避免内存泄漏 - 不建议缓存带强引用 ViewModel 或绑定上下文的页面,容易引发状态错乱
用 StateContainer 或属性持久化代替“页面缓存”
真正需要的往往不是页面对象缓存,而是数据与 UI 状态的延续:
- 将关键状态(如滚动位置、输入内容、筛选条件)保存到 ViewModel 的属性中,并标记为 [ObservableProperty] 或实现 INotifyPropertyChanged
- 利用 MAUI 的
App.Current.Properties或Preferences持久化轻量状态(如用户上次选中的 Tab) - 在
OnAppearing中恢复状态,比缓存整个页面更安全、更可控 - 对列表页,可结合
CollectionView.ScrollTo和SelectedItem恢复滚动与选中态
避免误用:什么不该缓存?
不是所有页面都适合缓存,盲目复用实例反而引发问题:
- 含实时传感器、相机预览、后台任务的页面——缓存会导致资源冲突或黑屏
- 多入口进入、参数差异大的页面(如 /user/1 vs /user/2)——应按参数区分缓存或禁用缓存
- 已调用
Navigation.PopAsync()弹出的页面——再次 Push 可能违反导航栈逻辑,建议统一用 Shell 或自定义导航服务封装 - WebView 页面——内部状态复杂,缓存易导致 JS 上下文异常,优先用重新加载 + URL 参数恢复
基本上就这些。MAUI 没有内置“安卓 Fragment 式”页面缓存,但通过 Shell 的 CacheNavigation、手动实例管理、状态分离这三种方式,可以覆盖绝大多数缓存需求。关键是分清:你要缓的是“页面对象”,还是“用户看到的内容”。后者往往更可靠、更轻量。










