ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Flutter # 路由管理

2022-02-04 18:05:31  阅读:215  来源: 互联网

标签:管理 BuildContext context new Navigator Flutter 路由 页面


路由(Route)在移动开发中通常指页面(Page),跟 Web 开发中单页应用的 Route 概念相同。Route 在 Android中 通常指一个 Activity,在 iOS 中指一个 ViewController。
路由管理/导航管理,管理页面之间如何跳转,会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作。


Demo

本文在示例计数器代码基础上做修改。

1.创建一个新路由,命名“NewRoute”。新路由继承自StatelessWidget。

class NewRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("New route"),
      ),
      body: Center(
        child: Text("This is new route"),
      ),
    );
  }
}

2.在_MyHomePageState.build方法中的Column的子widget中添加一个按钮(TextButton):

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    ... //省略无关代码
    TextButton(
      child: Text("open new route"),
      textColor: Colors.blue,
      onPressed: () {
        //导航到新路由   
        Navigator.push( 
          context,
          MaterialPageRoute(builder: (context) {
            return NewRoute();
          }),
        );
      },
    ),
  ],
 )

MaterialPageRoute继承自PageRoute类(抽象类):占有整个屏幕空间的模态路由,定义了路由构建及切换时过渡动画的相关接口及属性。

MaterialPageRoute({
    WidgetBuilder builder,
    RouteSettings settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  })

builder 回调函数,作用是构建路由页面具体内容,返回值是一个widget即新路由的实例。
settings 路由配置信息,路由名称、是否初始路由(首页)。
maintainState:默认当入栈新路由时,原路由仍保留,如果要释放可令maintainState为 false。
fullscreenDialog新路由页是否是一个全屏的模态对话框,在 iOS 中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。
(如果想自定义路由切换动画,可以自己继承 PageRoute 来实现)

Navigator

Navigator通过一个栈来管理活动路由集合。通常当前屏幕显示的页面就是栈顶的路由
Navigator类中第一个参数为context的静态方法都对应一个Navigator的实例方法, 比如Navigator.push(BuildContext context, Route route)等价于Navigator.of(context).push(Route route)。

Future push(BuildContext context, Route route)

将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据。

bool pop(BuildContext context, [ result ])

将栈顶路由出栈,result 为页面关闭时返回给上一个页面的数据。

路由传值

demo:TipRoute路由,接受一个提示文本参数,负责将传入它的文本显示在页面上,另外TipRoute中我们添加一个“返回”按钮,点击后在返回上一个路由的同时会带上一个返回参数

class TipRoute extends StatelessWidget {
  TipRoute({
    Key key,
    @required this.text,  // 接收一个text参数
  }) : super(key: key);
  final String text;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("提示"),
      ),
      body: Padding(
        padding: EdgeInsets.all(18),
        child: Center(
          child: Column(
            children: <Widget>[
              Text(text),
              ElevatedButton(
                onPressed: () => Navigator.pop(context, "我是返回值"),
                child: Text("返回"),
              )
            ],
          ),
        ),
      ),
    );
  }
}
class RouterTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () async {
          // 打开`TipRoute`,并等待返回结果
          var result = await Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) {
                return TipRoute(
                  // 路由参数
                  text: "我是提示xxxx",
                );
              },
            ),
          );
          //输出`TipRoute`路由返回结果
          print("路由返回值: $result");
        },
        child: Text("打开提示页"),
      ),
    );
  }
}

命名路由

使用命名路由必须先提供并注册一个路由表(routing table)。

Map<String, WidgetBuilder> routes;

注册路由表

MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
    ... // 省略其它路由注册信息
  } ,
  home: MyHomePage(title: 'Flutter Demo Home Page'),
);

上面的代码中home路由并没有使用命名路由,将home注册为命名路由改写:

initialRoute:"/", //名为"/"的路由作为应用的home(首页)
//注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
   "/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
  } 

通过路由名打开新路由页

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

eg:

Navigator.pushNamed(context, "new_page");

命名路由参数传递

 routes:{
   "new_page":(context) => EchoRoute(),
  } ,

路由页获取路由参数:

class EchoRoute extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    //获取路由参数  
    var args=ModalRoute.of(context).settings.arguments;
    //...省略无关代码
  }
}

打开路由时传递参数:

Navigator.of(context).pushNamed("new_page", arguments: "hi");

路由生成钩子

(onGenerateRoute只对命名路由生效)
MaterialApp有一个onGenerateRoute属性在打开命名路由时可能会被调用(调用Navigator.pushNamed()打开命名路由时,如果路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件,否则才走onGenerateRoute)。

onGenerateRoute回调签名如下:

Route<dynamic> Function(RouteSettings settings)
MaterialApp(
  ... //省略无关代码
  onGenerateRoute:(RouteSettings settings){
	  return MaterialPageRoute(builder: (context){
		   String routeName = settings.name;
       // 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
       // 引导用户登录;其它情况则正常打开路由。
     }
   );
  }
);

标签:管理,BuildContext,context,new,Navigator,Flutter,路由,页面
来源: https://blog.csdn.net/qq_33583069/article/details/122784127

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有