You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Navigator2.0页面栈恢复方案咨询:替代Navigator.restorablePush方法

在Navigator2.0中,确实有对应的页面栈状态恢复方案,但不能直接依赖Navigator1.0的restorablePush——你推测的原因是对的:Navigator2.0的页面栈完全由RouterDelegate维护的pages列表驱动,Activity销毁时如果没有持久化这个列表的状态,重建后RouterDelegate会回到初始状态,导致之前的页面栈丢失。

核心解决思路

要实现Navigator2.0的页面栈恢复,关键是持久化RouterDelegate中页面栈的状态,而不是依赖Navigator的restorable方法。具体步骤如下:

  1. 定义可序列化的页面状态模型
    给每个页面创建一个包含路由名、必要参数的模型,实现序列化/反序列化逻辑,方便持久化。

  2. 在RouterDelegate中管理页面状态
    用这个模型列表替代直接维护Page对象,每次页面跳转时更新该列表并持久化。

  3. 结合状态恢复机制与本地存储

    • 用Flutter的RestorationMixin处理配置变更(如屏幕旋转)的状态恢复。
    • 用本地存储(如SharedPreferences)处理Activity销毁后重启的状态恢复。

代码示例

1. 页面状态模型

class PageState {
  final String routeName;
  final Map<String, dynamic>? arguments;

  PageState(this.routeName, this.arguments);

  // 序列化
  Map<String, dynamic> toJson() => {
        'routeName': routeName,
        'arguments': arguments,
      };

  // 反序列化
  factory PageState.fromJson(Map<String, dynamic> json) => PageState(
        json['routeName'],
        json['arguments'] as Map<String, dynamic>?,
      );
}

2. 带状态恢复的RouterDelegate

class AppRouterDelegate extends RouterDelegate<Uri> with RestorationMixin {
  final _restorationId = 'app_router';
  final List<PageState> _pageStates = [PageState('/', null)]; // 初始页面

  // 用于Flutter内置状态恢复的可恢复列表
  final RestorableList<PageState> _restorablePageStates =
      RestorableList<PageState>(defaultValue: []);

  @override
  String? get restorationId => _restorationId;

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(_restorablePageStates, 'page_states_list');
    // 从本地存储恢复页面栈(处理Activity销毁重启)
    _loadSavedPageStates();
  }

  // 从SharedPreferences加载持久化的页面状态
  Future<void> _loadSavedPageStates() async {
    final prefs = await SharedPreferences.getInstance();
    final jsonStrings = prefs.getStringList('saved_page_states');
    if (jsonStrings != null) {
      _pageStates.clear();
      _pageStates.addAll(jsonStrings
          .map((json) => PageState.fromJson(jsonDecode(json)))
          .toList());
      _restorablePageStates.value = _pageStates;
      notifyListeners();
    }
  }

  // 持久化页面状态到SharedPreferences
  Future<void> _savePageStates() async {
    final prefs = await SharedPreferences.getInstance();
    final jsonStrings = _pageStates
        .map((state) => jsonEncode(state.toJson()))
        .toList();
    await prefs.setStringList('saved_page_states', jsonStrings);
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      pages: _pageStates.map((state) {
        switch (state.routeName) {
          case '/':
            return MaterialPage(key: const ValueKey('/'), child: const HomePage());
          case '/detail':
            return MaterialPage(
              key: ValueKey('/detail-${state.arguments?['id']}'),
              child: DetailPage(arguments: state.arguments),
            );
          default:
            return MaterialPage(key: const ValueKey('/404'), child: const NotFoundPage());
        }
      }).toList(),
      onPopPage: (route, result) {
        if (!route.didPop(result)) return false;
        if (_pageStates.length > 1) {
          _pageStates.removeLast();
          _savePageStates();
          notifyListeners();
        }
        return true;
      },
    );
  }

  // 自定义跳转方法,更新页面栈并持久化
  void pushPage(String routeName, [Map<String, dynamic>? arguments]) {
    _pageStates.add(PageState(routeName, arguments));
    _savePageStates();
    notifyListeners();
  }

  // 实现RouterDelegate的其他必要方法
  @override
  Future<void> setNewRoutePath(Uri configuration) async {
    // 处理深层链接逻辑(可选)
  }

  @override
  Uri? get currentConfiguration => Uri.parse(_pageStates.last.routeName);
}

注意事项

  • 禁止混用Navigator1.0的push/restorablePush方法:这些方法不会更新RouterDelegate的pages列表,导致页面栈状态不一致。
  • 页面状态要精简:只存储必要的参数(如ID、路由名),不要存储大数据或上下文对象。
  • 区分场景:RestorationMixin适合处理配置变更(如旋转屏幕),本地存储适合处理App重启、Activity销毁后的恢复。

内容的提问来源于stack exchange,提问作者Matsuyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:08:21