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.child.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.child.runtimeType == page.runtimeType) {
        // 更新栈顶页面的参数
        final lastPage = _pages.removeLast();
        _result.remove(lastPage.hashCode);

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

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

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

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