Flutter 中的跳转

293 阅读4分钟

在 Flutter 中,页面跳转(导航)是通过 Navigator 组件管理的,其核心原理是基于 页面栈(Stack) 的机制。以下是 Flutter 中常见的跳转方式,从使用场景、实现方式和底层原理三个角度进行总结:


一、基础跳转方式

1. Navigator.push / Navigator.pop

  • 使用场景:最常见的页面跳转方式,适合简单的页面层级导航(如 A → B → C)。
  • 实现方式
    // 跳转到新页面
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SecondPage()),
    );
    
    // 返回上一页
    Navigator.pop(context);
    
  • 底层原理
    • Navigator 是一个管理页面栈的组件,push 会将新页面压入栈顶并显示,pop 会移除当前页面并显示前一个页面。
    • 页面栈的每个页面是一个 Route 对象(如 MaterialPageRoute)。

2. Navigator.pushReplacement

  • 使用场景:替换当前页面为新页面(如登录成功后跳转到主页,无需返回登录页)。
  • 实现方式
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => HomePage()),
    );
    
  • 底层原理
    • 移除当前页面,将新页面压入栈顶。页面栈长度减少 1。

3. Navigator.pushAndRemoveUntil

  • 使用场景:跳转到新页面并清除所有之前的页面(如退出登录后跳转到登录页)。
  • 实现方式
    Navigator.pushAndRemoveUntil(
      context,
      MaterialPageRoute(builder: (context) => LoginPage()),
      (route) => false, // 清除所有页面
    );
    
  • 底层原理
    • 清除页面栈中所有页面,直到满足条件(until 回调返回 true),然后压入新页面。

二、命名路由跳转

4. Navigator.pushNamed / Navigator.popUntil

  • 使用场景:大型应用中管理多个页面,通过路由名称跳转(如配置路由表)。
  • 实现方式
    // 配置路由表(通常在 MaterialApp 中)
    MaterialApp(
      routes: {
        '/home': (context) => HomePage(),
        '/detail': (context) => DetailPage(),
      },
    );
    
    // 跳转到命名路由
    Navigator.pushNamed(context, '/detail');
    
    // 返回到指定页面
    Navigator.popUntil(context, ModalRoute.withName('/home'));
    
  • 底层原理
    • 路由名称与 onGenerateRouteroutes 表映射,通过名称查找对应的 RouteBuilder 生成页面。

三、自定义跳转动画

5. 自定义 PageRoute

  • 使用场景:需要自定义页面切换动画(如从底部滑入、缩放等)。
  • 实现方式
    class CustomPageRoute extends PageRouteBuilder {
      final Widget page;
    
      CustomPageRoute({required this.page})
          : super(
            pageBuilder: (context, animation, secondaryAnimation) => page,
            transitionsBuilder: (context, animation, secondaryAnimation, child) {
              return FadeTransition(opacity: animation, child: child);
            },
          );
    }
    
    // 使用自定义动画跳转
    Navigator.push(context, CustomPageRoute(page: DetailPage()));
    
  • 底层原理
    • 继承 PageRouteBuilder,通过 transitionsBuilder 定义动画逻辑,覆盖默认的 MaterialPageRoute 动画。

四、跨页面通信

6. 传递参数与返回结果

  • 使用场景:跳转页面时传递数据,并从目标页面返回结果。

  • 实现方式

    // 跳转并传递参数
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => DetailPage(data: 'Hello'),
      ),
    );
    
    // 目标页面返回结果
    Navigator.pop(context, 'Result from DetailPage');
    
    // 原页面接收结果
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => DetailPage()),
    );
    print(result); // 输出 'Result from DetailPage'
    
  • 底层原理

    • push 返回一个 Future,当 pop 传递值时,Future 会解析为该值。

五、全局导航管理(高级)

7. 使用 Navigator 2.0Router API)

  • 使用场景:复杂路由管理(如动态路由、深度链接、状态同步)。
  • 实现方式
    class MyRouter extends RouterDelegate {
      @override
      Widget build(BuildContext context) => MyHomePage();
    
      @override
      Future<void> setNewRoutePath(configuration) async {}
    
      @override
      Route? onGenerateRoute(RouteSettings settings) {
        return MaterialPageRoute(builder: (context) => MyHomePage());
      }
    }
    
    MaterialApp.router(routerDelegate: MyRouter());
    
  • 底层原理
    • Navigator 2.0 提供更细粒度的路由控制,通过 RouterDelegateRouteInformationParser 管理 URL 和页面状态。

六、第三方库跳转(补充)

1. 使用 Get 库(GetX 框架)

  • 使用场景:简化导航和状态管理(适合中小型项目)。
  • 实现方式
    // 跳转页面
    Get.to(DetailPage());
    
    // 返回上一页
    Get.back();
    
    // 传递参数
    Get.to(DetailPage(), arguments: {'id': 1});
    
    // 接收参数
    var id = Get.arguments['id'];
    
  • 底层原理
    • Get 封装了 Navigator,通过单例管理页面栈,支持依赖注入和状态管理。

七、总结对比

跳转方式适用场景优点缺点
push/pop基础页面跳转简单直接动画固定,需手动管理参数
pushReplacement替换当前页面清理页面栈无法返回到被替换页面
pushAndRemoveUntil清除历史页面强制跳转到指定页面逻辑复杂
命名路由大型应用统一管理路由表清晰需预先配置路由
自定义 PageRoute动画定制灵活实现复杂
Navigator 2.0复杂路由、深度链接完全控制路由状态学习曲线陡峭
Get快速开发、简化导航语法简洁,集成状态管理依赖第三方库

八、底层原理详解

  1. 页面栈(Stack)

    • 所有页面通过 Navigator 管理,形成一个栈结构。push 添加页面到栈顶,pop 移除当前页面。
  2. Route 对象

    • 每个页面是一个 Route 对象(如 MaterialPageRoute),负责渲染页面和动画过渡。
  3. 动画系统

    • MaterialPageRoute 使用 Hero 动画和 PageRouteBuilder 实现平台默认动画。
    • 自定义动画通过 PageRouteBuildertransitionsBuilder 实现。
  4. 生命周期管理

    • 页面进入时调用 Route.didPush(),离开时调用 Route.didPop()
    • 页面可见性通过 Route.willChangeInternalState 控制。

通过合理选择跳转方式,结合场景需求和项目复杂度,可以高效构建 Flutter 应用的导航逻辑。