Flutter命名路由食用指北

配置

需要在main.dart文件的第一个MaterialApp中配置命名路由信息:

import 'package:iting/constant/route_config.dart';
import 'package:flutter/material.dart';

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      ///默认不显示debug
      debugShowCheckedModeBanner: false,

      theme: ThemeData(primaryColor: Colors.orange),

      ///命名路由表
      routes: namedRoutes,

      ///注入路由表,当路由没有在命名路由表中注册时调用
      onGenerateRoute: onGenerateRoute,

      ///404
      onUnknownRoute: onUnknownRoute,

      ///具体页面
      home: Scaffold(
        resizeToAvoidBottomPadding: false,
        body: ...,
      ),
    );
  }
}

这里是通过引入外部命名路由文件route_config.dart进行路由信息的配置,当然也可以在对应参数后面直接配置对应类型的数据
route_config.dart配置文件:

import 'package:flutter/material.dart';

import '../404notfound.dart';

final Map<String, WidgetBuilder> namedRoutes = {
  PageA.pageName: (ctx) => PageA(),
};

final Route<dynamic> Function(RouteSettings settings) onGenerateRoute =
    (settings) {
  WidgetBuilder builder;
  if (settings.name == PageB.pageName) {
    builder = (context) => PageB(page_b_id: settings.arguments);
  }
  return MaterialPageRoute(
    builder: (context) {
      return builder(context);
    },
  );
};

final Route<dynamic> Function(RouteSettings settings) onUnknownRoute =
    (settings) {
  return MaterialPageRoute(
    builder: (context) {
      return NotFoundPage();
    },
  );
};

PageA.dart

class PageA extends StatefulWidget {
  static final String pageName = "PageA";

  @override
  _PageAState createState() => _PageAState();
}

class _PageAState extends State<PageA> {
  var value = ModalRoute.of(context).settings.arguments;
  @override
  Widget build(BuildContext context) {
    return Container(
      ...
    );
  }
}

PageB.dart

class PageB extends StatefulWidget {
  static final String pageName = "PageB";
  
  PageB({int page_b_id});

  @override
  _PageBState createState() => _PageBState();
}

class _PageBState extends State<PageB> {
  @override
  Widget build(BuildContext context) {
    return Container(
    ...
    );
  }
}

参数

routes:命名路由表,返回Map<String, WidgetBuilder>类型的数据,通过命名路由跳转界面时会首先从这个Map中寻找对应的页面,如果找到则进行跳转

onGenerateRoute:路由拦截表,返回一方法,方法以RouteSettings为参数,Route<dynamic>为返回值,再routes中没有查询到的路由会进入这里面进行查询匹配

onUnknownRoute:如果上面查询都失败了,则会调用此方法,可以这里处理返回信息,我在这里是返回一个404的页面

使用与传参

配置了这些信息,就可以:

  1. 通过Navigator.of(context).pushNamed(PageA.pageName);跳转到PageA
  2. 通过Navigator.of(context).pushNamed(PageB.pageName,arguments: 123);跳转到PageB,并在onGenerateRoute匹配路由名称,用setting获取路由信息,并通过构造函数传参
  3. 通过Navigator.of(context).pushNamed(PageA.pageName,arguments: 123);跳转到PageA,通过无构造函数传参,在目标页面,通过ModalRoute.of(context).settings,在build方法中获取路由信息和对应参数。
    无构造传参的方式在StatefulWidget中的initState生命周期方法中调用ModalRoute.of(context)会报错,原因是context尚未初始化完成不能使用,直到state相关framework关联完成才可以使用;如果需要初始化时就要使用,则可以通过构造函数传参,并通过widget传递给state

返回与回调

通常我们使用Navigatorpop方法进行路由的回退

Navigator.of(context).pop();

Navigator的方法中所有带push的方法会返回带泛型的Future
同理,NavigatorpopmaybePoppopAndPushNamed方法参数中会携带一个参数
路由传参回调主要是通过就是通过这两者结合起来的
跳转:

Navigator.of(context)
    .pushNamed(routerName, arguments: arguments)
    .then((value) {
  print("value ${value}");
});

返回:

Navigator.of(context).pop(true);

注意

通过上面的配置确实已经可以完成命名路由的配置和使用
但是在诸如Navigator.xxxxUntil的路由方法中,通过RoutePredicate参数打印已经经历过的路由路径信息时会发现,那些没有在routes中配置,直接通过onGenerateRoute中匹配的路由路径返回的信息是null,这样就导致了Navigator.xxxxUntil方法使用的局限性,你会找不到停靠的目标页面
为了解决这一问题,上述的onGenerateRoute中需要做如下修改:

final Route<dynamic> Function(RouteSettings settings) onGenerateRoute =
    (settings) {
  WidgetBuilder builder;
  if (settings.name == PageB.pageName) {
    builder = (context) => PageB(page_b_id: settings.arguments);
  }
  return MaterialPageRoute(
    settings: RouteSettings(
      name: settings.name,
      arguments: settings.arguments,
    ),
    builder: (context) {
      return builder(context);
    },
  );
};

在返回MaterialPageRoute时,通过setting参数传入路由信息RouteSettings

至此,命名路由管路指北结束,撒花✿✿✿✿ヽ(°▽°)ノ✿✿✿✿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值