flutter Route路由基本用法

本文深入解析Flutter中的命名路由、路由组、路由退出及路由堆栈的使用。介绍如何通过Navigator进行页面跳转,包括命名路由、匿名路由的使用,以及如何在路由跳转中传递参数。同时,探讨了路由集合(路由表)与onGenerateRoute的关系,提供了实例代码,帮助开发者更好地理解和运用Flutter路由。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flutter 命名路由、路由组、路由退出、路由堆栈

在flutter中需要进行页面跳转,也是需要用到路由Route,关键Navigator与Route,Navigator负责单元Route路由,压入和弹出,单元路由也就是我们需要跳转页面 ,比如HomePage()

Navigator关键使用的4个属性

•initialRoute: 初始路由的,也就是进入APP,默认页面
•onGenerateRoute: 路由拦截器
•onUnknownRoute: 找不到页面,也就是404
•routes : 路由集合,也就在执行路由跳转的时候,会到路由集合里面的子路由进行匹配,如果匹配 到那么就调整到指定页面


路由跳转 方式:

1.通过路由名打开新路由页面

通过路由名称来打开新路由,可以使用Navigator 的pushNamed方法:

Future pushNamed(BuildContext context, String routeName,{Object arguments})

调用:

onPressed: () {
//不带参数
  Navigator.pushNamed(context, "new_page");
  //带参数,可以指定单个参数,或者多个, arguments: {}
  Navigator.of(context).pushNamed("new_page", arguments: "hi");
},

页面承接带过来的参数

  String tmp = ModalRoute.of(context).settings.arguments.toString();
2.匿名路由打开新路由页面
Navigator.push( context, MaterialPageRoute(builder: (context) {
              return HomePage();
           }));

传参:

  final Map<String, WidgetBuilder> _routes = {
    '/sign': (context, {arguments}) => SignPage(arguments: arguments),
  };

接参:

class SignPage extends StatelessWidget {
  final Map arguments;
  SignPage({Key key, this.arguments}) : super(key: key) {
  }

  @override
  Widget build(BuildContext context) {
    String tmp2 = this.arguments.toString();
  }
}

路由集合(路由表)与onGenerateRoute的关系
onGenerateRoute接受一个 Route 工厂函数

final RouteFactory onGenerateRoute;

路由拦截源码,从拦截到路由之后,首先从路由表中拿到路由的 builder,如果能够拿到 builder,则判断是否存在 RouteSettings,如果存在则直接通关构造函数的 arguments 传递给页面 Page Widget。本质就是按照路由名字匹配路由表,然后跳转到正确页面中

Route _routeGenerator(RouteSettings settings) {
    final String name = settings.name;
    final Function pageBuilder = this._routes[name];
    if (pageBuilder != null) {
      if (settings.arguments != null) {
        // 如果透传了参数
        return MaterialPageRoute(
            builder: (context) =>
                pageBuilder(context, arguments: settings.arguments));
      } else {
        // 没有透传参数
        return MaterialPageRoute(builder: (context) => pageBuilder(context));
      }
    }
    return MaterialPageRoute(builder: (context) => HomeContent());
  }

路由的使用方式
第一个种,初始化执行路线,initialRoute -> onGenerateRoute -> onUnknownRoute, 路由跳转Navigator.pushNamed(context, “secondPage”); ,之后会到onGenerateRoute ,进行路由拦截匹配,如果能正确匹配到,那么跳转到指定页面
例子:

import 'package:flutter/material.dart';
 
class NavigatorPage extends StatefulWidget {
 @override
 _NavigatorPageState createState() => _NavigatorPageState();
}
 
class _NavigatorPageState extends State<NavigatorPage> {
 @override
 Widget build(BuildContext context) {
  return Scaffold(
   appBar: AppBar(
    title: Text('Navigator'),
   ),
   body: Column(
    children: <Widget>[
     Text('Navigator的高度为infinity'),
     Text('如果直接父级非最上级也是infinity会产生异常'),
     Container(
      height: 333,
      color: Colors.amber.withAlpha(111),
      child: Navigator( // Navigator
       initialRoute: '/abc',
       onGenerateRoute: (val) {
        RoutePageBuilder builder;
        switch (val.name) {
         case '/abc':
          builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Column(
           // 并没有在 MaterialApp 中设定 /efg 路由
           // 因为Navigator的特性 使用nContext 可以跳转 /efg
           children: <Widget>[
            Text('呵呵呵'),
            RaisedButton(
             child: Text('去 /efg'),
             onPressed: () {
              Navigator.pushNamed(nContext, '/efg');
             },
            )
           ],
          );
         break;
         case '/efg':
          builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Row(
           children: <Widget>[
            RaisedButton(
             child: Text('去 /hhh'),
             onPressed: () {
              Navigator.pushNamed(nContext, '/hhh');
             },
            )
           ],
          );
         break;
         default:
          builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Center(
           child: RaisedButton(
            child: Text('去 /abc'),
            onPressed: () {
             Navigator.pushNamed(nContext, '/abc');
            },
           )
          );
        }
        return PageRouteBuilder(
         pageBuilder: builder,
         // transitionDuration: const Duration(milliseconds: 0),
        );
       },
       onUnknownRoute: (val) {
        print(val);
       },
       observers: <NavigatorObserver>[]
      ),
     ),
     Text('Navigator执行寻找路由顺序'),
     Text('initialRoute'),
     Text('onGenerateRoute'),
     Text('onUnknownRoute'),
    ],
   ),
  );
 }
}

第二个种,初始化执行路线,routes ->onUnknownRoute,路由跳转Navigator.pushNamed(context, “secondPage”);,之后会到routes 路由集合之后,能匹配到正确的路由子路由,那么就跳转到子路由中
例子:

import 'package:flutter/material.dart';
import 'package:flutter_routes/errorpage.dart';
import 'package:flutter_routes/homepage.dart';
import 'package:flutter_routes/navigator_with_result.dart';
import 'package:flutter_routes/page1.dart';
import 'package:flutter_routes/page2.dart';
import 'package:flutter_routes/page3.dart';
import 'package:flutter_routes/page4.dart';
import 'package:flutter_routes/page5.dart';
import 'package:flutter_routes/pageroutebuilderresult.dart';
import 'package:flutter_routes/splash.dart';
import 'package:flutter_routes/testpageroutebuilder.dart';
import 'package:flutter_routes/todo.dart';
import 'package:flutter_routes/welcome.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter路由',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
//      路由集合
      routes: {
        '/page1': (context) => Page1(),
        '/page2': (context) => Page2(),
        '/page3': (context) => Page3(),
        '/page4': (context) => Page4(),
        '/page5': (context) => Page5(),
        '/todo': (context) => TodosScreen(),
        '/splash': (context) => Splash(),
        '/welcome': (context) => Welcome(),
        '/homepage': (context) => HomePage(),
        '/PageRouteBuilder': (context) => TestPageRouteBuilder(),
        '/PageRouteBuilderResult': (context) => PageRouteBuilderResult(),
      },
//      找不到路由,显示的错误页面
      onUnknownRoute: (RouteSettings setting) {
        String name = setting.name;
        print("未匹配到路由:$name");
        return new MaterialPageRoute(builder: (context) {
          return new ErrorPage();
        });
      },
      home: Page1(),
    );
  }
}

Page1 页面

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class Page1 extends StatelessWidget {

  Page1({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('page1'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('跳转到Page2'),
          onPressed: () {
//            路由跳转
            Navigator.pushNamed(context, '/page2');
          },
        ),
      ),
    );
  }
}

在实际开发过程中,建议用命名路由方式来跳转新的页面,便于维护,开发项目

路由堆栈的使用方式
1、在用这种方式路由跳转新页面的时候,是把页面放在堆栈里面,这个栈的特性就是,先进后出, Navigator.push 或者 pushNamed 实现的,每次都是把页面压入堆栈,在回退 的时候会回退到上一跳页面

Navigator.of(context).pushNamed('/search');

2.如果需要清空堆栈,比如我需要直接返回首页,之前的所有路由全部干掉,堆栈清空

Navigator.of(context).pushNamedAndRemoveUntil

页面退出堆栈

 Navigator.pop(context, "我是返回值"),

参考文章
https://blog.youkuaiyun.com/weixin_30512027/article/details/85334391
https://blog.youkuaiyun.com/weixin_34999505/article/details/86760606

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值