push<T> method

Future<void> push<T>({
  1. required Widget page,
  2. ResultCallback? onResult,
  3. String? name,
  4. Object? arguments,
  5. String? restorationId,
  6. bool maintainState = true,
  7. bool fullscreenDialog = false,
  8. bool allowSnapshotting = true,
  9. LaunchMode launchMode = LaunchMode.standard,
})

推出一个新页面到导航栈

Implementation

Future<void> push<T>(
    {required Widget page,
    ResultCallback? onResult,
    String? name,
    Object? arguments,
    String? restorationId,
    bool maintainState = true,
    bool fullscreenDialog = false,
    bool allowSnapshotting = true,
    LaunchMode launchMode = LaunchMode.standard}) async {
  // 执行路由守卫检查(基于路由名称)
  final from = RouteInformation(uri: Uri.parse(_location ?? '/'));
  final to =
      RouteInformation(uri: Uri.parse(name ?? page.runtimeType.toString()));
  final canNavigate = await _checkRouteGuards(from, to);
  if (!canNavigate) {
    return;
  }

  // 执行页面类型守卫检查
  final fromPageType =
      _pages.isNotEmpty ? _pages.last.page.runtimeType : null;
  final toPageType = page.runtimeType;
  final canNavigateByType =
      await _checkPageTypeGuards(fromPageType, toPageType);
  if (!canNavigateByType) {
    return;
  }

  final routeSettings = RouteSettings(
      name: name ?? page.runtimeType.toString(), arguments: arguments);

  // 处理启动模式
  switch (launchMode) {
    case LaunchMode.singleTop:
      // 如果栈顶已是该页面类型,则更新参数而不创建新实例(类似Android的onNewIntent)
      if (_pages.isNotEmpty &&
          _pages.last.page.runtimeType == page.runtimeType) {
        // 更新栈顶页面的参数
        final lastPage = _pages.removeLast();
        _result.remove(lastPage.materialPage.hashCode);

        final updatedPage = _createPageEntry(
          page: page,
          name: routeSettings.name,
          arguments: routeSettings.arguments,
          restorationId: restorationId,
          maintainState: maintainState,
          fullscreenDialog: fullscreenDialog,
          allowSnapshotting: allowSnapshotting,
        );
        _pages.add(updatedPage);
        _result[updatedPage.materialPage.hashCode] = onResult;
        _location = routeSettings.name;
        notify();
        return;
      }
      break;
    case LaunchMode.singleInstance:
      // 如果栈中已存在该页面,清除它上面的所有页面,并更新参数(类似Android的onNewIntent)
      final existingIndex = _pages.indexWhere(
          (element) => element.page.runtimeType == page.runtimeType);

      if (existingIndex != -1) {
        // 找到已存在的页面
        // 1. 清除该页面上面的所有页面
        final pagesToRemove = _pages.sublist(existingIndex);
        for (var pageToRemove in pagesToRemove) {
          _result.remove(pageToRemove.materialPage.hashCode);
        }
        _pages.removeRange(existingIndex, _pages.length);

        // 2. 用新参数重新创建该页面(类似onNewIntent)
        final updatedPage = _createPageEntry(
          page: page,
          name: routeSettings.name,
          arguments: routeSettings.arguments,
          restorationId: restorationId,
          maintainState: maintainState,
          fullscreenDialog: fullscreenDialog,
          allowSnapshotting: allowSnapshotting,
        );
        _pages.add(updatedPage);
        _result[updatedPage.materialPage.hashCode] = onResult;
        _location = routeSettings.name;
        notify();
        return;
      }
      // 如果不存在,继续执行后面的代码创建新实例
      break;
    case LaunchMode.standard:
      // 标准模式,不做特殊处理
      break;
  }

  final target = _createPageEntry(
    page: page,
    name: routeSettings.name,
    arguments: routeSettings.arguments,
    restorationId: restorationId,
    maintainState: maintainState,
    fullscreenDialog: fullscreenDialog,
    allowSnapshotting: allowSnapshotting,
  );
  _pages.add(target);
  _result[target.materialPage.hashCode] = onResult;
  _location = routeSettings.name;
  notify();
}