[Flutter开发]03.Flutter中的路由管理

2020-03-10  本文已影响0人  沈枫_SerenF

Flutter中的路由管理,就是管理页面之间如何跳转。无论是Android还是iOS,导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面(或者叫新路由),路由出栈(pop)操作对应页面关闭操作,而路由管理主要是指如何来管理路由栈。

而路由管理需要用到以下组件,我们分别来认识一下。

Navigator

Navigator提供了一系列方法来管理路由栈:

  1. Future push(BuildContext context, Route route),此方法是静态方法:
Navigator.push(BuildContext context, Route route)

对应的实例方法是:

Navigator.of(context).push(Route route)
  1. bool pop(BuildContext context, [ result ])

result为页面关闭时返回给上一个页面的数据。

MaterialPageRoute

MaterialPageRoute用来构建Route,构建函数如下:

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

以上的方式是非命名路由,下面我来讲一下命名路由。

命名路由

所谓命名路由,无非就是先给路由起一个名字,然后就可以通过路由名字直接打开新的路由了,这为路由管理带来了一种直观、简单的方式。

我们可以通过注册路由表的方式,然后通过路由名字打开新路由时,在路由表中,一个名字对应一个生成相应的路由的回调函数,应用会根据路由名字在路由表中查找到对应的回调函数(WidgetBuilder),然后调用该回调函数生成路由widget并返回。

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

要通过路由名称来打开新路由,也很简单:

Navigator.pushNamed(context, "new_page");

或者:

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

我们看到上面的第二个push方法中传递一个参数'hi',那么在新路由中实际上可以通过RouteSetting对象获取这个参数:

class EchoRoute extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    //路由参数  
    var args=ModalRoute.of(context).settings.arguments;
    //...
  }
}

onGenerateRoute

MaterialApp有一个onGenerateRoute属性,当调用Navigator.pushNamed(...)打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果路由表中没有注册,就会调用onGenerateRoute来生成路由。一般我们可以在该回调中进行统一的权限控制,比如:

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

WillPopScope

Flutter中可以通过WillPopScope来实现导航返回按钮拦截。其默认构造函数如下:

const WillPopScope({
  ...
  @required WillPopCallback onWillPop,
  @required Widget child
})

其中,onWillPop是一个回调函数,当用户点击返回按钮时被调用。该回调需要返回一个Future对象,如果返回的Future最终值为false时,则不会返回;如果最终值为true时,当前路由出栈退出。我们需要提供这个回调来决定是否退出。

举个例子,为了防止用户误触返回键退出,我们设定当用户在1秒内点击两次返回按钮时,则退出;如果间隔超过1秒则不退出,并重新记时。代码如下:

class TestRoute extends StatefulWidget {
  @override
  TestRouteState createState() {
    return new TestRouteState();
  }
}

class TestRouteState extends State<TestRoute> {
  DateTime _lastClickTime; //上次点击时间

  @override
  Widget build(BuildContext context) {
    return new WillPopScope(
        onWillPop: () async {
          if (_lastClickTime == null ||
              DateTime.now().difference(_lastClickTime) > Duration(seconds: 1)) {
            //两次点击间隔超过1秒则重新计时
            _lastClickTime = DateTime.now();
            return false;
          }
          return true;
        },
        child: Container(
          alignment: Alignment.center,
          child: Text("test demo"),
        )
    );
  }
}
上一篇下一篇

猜你喜欢

热点阅读