flutter onGenerateRoute原生路由简单封装及

2021-04-28  本文已影响0人  小话001

在主入口文件main.dart中尽量是做到简洁,如图示例就相对复杂了:

错误示范.jpg
其中,routes(map对象):是项目的各个页面路由配置
initialRoute:是项目的根路由,初始化的时候最先展示的页面
onGenerateRoute(RouteFactory类型函数):路由钩子,可以对某些指定的路由进行拦截,有时候不想改变页面结构,但是又想要求跳转到这个页面的时候可以用到,比如,页面设定了传参你进行跳转的时候。
onUnknownRoute(RouteFactory类型函数):在路由匹配不到的时候用到,一般都返回一个统一的错误页面或404页面

解决方式:
在项目的目录下新建route.dart

class MYRouter {
  static final Map<String, WidgetBuilder> routes = {
    MYHomePage.routeName: (ctx) =>MYHomePage(), // 记得在页面里面 声明静态变量 static const String routeName = "/";
    MYAboutPage.routeName: (ctx) => MYAboutPage()//  声明静态变量 static const String routeName = "/about";
  };
  static final String initialRoute = MYHomePage.routeName;
  static final RouteFactory generateRoute = (settings) {
    if (settings.name == MYDetailPage.routeName) {
      return MaterialPageRoute(
          builder: (ctx) {
            return MYDetailPage(settings.arguments);
          }
      );
    }
    return null;
  };
  static final RouteFactory unknownRoute = (settings) {
    return MaterialPageRoute(
        builder: (ctx) {
          return MYUnknownPage();
        }
    );
  };
}

抽离后在main.dart再使用的时候会简洁很多了:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          primarySwatch: Colors.blue, splashColor: Colors.transparent),
      routes: MYRouter.routes,
      initialRoute: MYRouter.initialRoute,
      onGenerateRoute: MYRouter.generateRoute,
      onUnknownRoute: MYRouter.unknownRoute,
    );
  }
}

常见的跳转方法:

//第一种:普通
    Future result = Navigator.of(context).push(MaterialPageRoute(
      builder: (ctx) {
        return MYDetailPage("a home message");
      }
    ));
 可以在MYDetailPage调用_backToHome方法的时候Navigator.of(context).pop("a detail message");以便父组件(main.dart)接收到值
// 第二种:带参数
Navigator.of(context).pushNamed(MYAboutPage.routeName, arguments: "a home message");
下级页面接收参数(注意:接收参数位置的地方对应三种方法): final String message = ModalRoute.of(context).settings.arguments as String;

about.dart

import 'dart:async';
import 'package:flutter/material.dart';
class MYAboutPage extends StatefulWidget {
  static const String routeName = "/about";
  @override
  _MYAboutPageState createState() => _MYAboutPageState();
}
class _MYAboutPageState extends State<MYAboutPage> {
  @override
  void initState() {
    super.initState();
   // 第二种:如果在initState拿参数可以采用
    Future.delayed(Duration.zero, () {
      final String message = ModalRoute.of(context).settings.arguments as String;
      print(message);
    });
 // 第三种:如果在initState拿参数可以采用
    Timer.run(() {
      final String message = ModalRoute.of(context).settings.arguments as String;
      print(message);
    });
  }
  @override
  Widget build(BuildContext context) {
    // 第一种:通常是在这拿参数
    final String message = ModalRoute.of(context).settings.arguments as String;
    return Scaffold(
      appBar: AppBar(
        title: Text("关于页"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(message),
            RaisedButton(
              child: Text("返回首页"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            )
          ],
        ),
      ),
    );
  }
}

说明:针对onGenerateRoute,因为假设页面是这样:
detail.dart

import 'package:flutter/material.dart';
class MYDetailPage extends StatelessWidget {
// 当前页面肯定是要接收参数_message的,是必须的参数,也可以用required修饰强调
  static String routeName="/detail";
  final String _message;
  DetailPage(this._message);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("详情页"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_message, style: TextStyle(fontSize: 20),),
            ElevatedButton (
              child: Text("回到首页"),
              onPressed: () => _backToHome(context),
            )
          ],
        ),
      ),
    );
  }
  void _backToHome(BuildContext context) {
    Navigator.of(context).pop("a detail message");
  }
}

如果按照正常的pushName逻辑跳转方法的话:

  _jumpToDetail(BuildContext context) {
    final res = Navigator.of(context).pushNamed(DetailPage.routeName, arguments: "我是参数");
    /*  如果 采用这种方式 那么路由的配置就应该变为
       routes:{
           HomePage.routeName:(ctx)=>HomePage(),
           "/detail":(ctx)=>DetailPage()       //现在这样肯定是报错,而这个页面是需要必传参数的,所以 也不能写死为"/detail":(ctx)=>DetailPage("123")
       }
      // 所以在不改变DetailPage页面结构的情况下 必须使用路由钩子函数onGenerateRoute
     */

所以在这种情况下就适合使用钩子函数.

上一篇 下一篇

猜你喜欢

热点阅读