Flutter 配置路由跳转、传参、路由守卫

4,214 阅读4分钟

新建Routes文件

在项目的 lib 目录下新建 routes 目录,在 routes 目录下新建 routes.dart 文件。

1. 首选需要引入,不然会报错。

import "package:flutter/material.dart";

2. 引入页面文件

import 'package:fushikang_flutter/pages/login_page.dart';
import 'package:fushikang_flutter/pages/index_page.dart';

3. 配置命名路由

final routes = {
  '/index': (context) => IndexPage(),
};

//固定写法
var onGenerateRoute = (RouteSettings settings) {
  // 统一处理
  final String name = settings.name;
  final Function pageContentBuilder = routes[name];
  final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context));
  return route;
};

'/index'是路由名称,这样我们的 routes.dart 文件就配置好了。

配置 main.dart

1. 我们回到 mian.dart 首先需要把routes文件引入到main中。

import 'routes/routes.dart';

2. 配置路由

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      initialRoute: '/index', // 这是配置加载的第一个页面
      onGenerateRoute: onGenerateRoute, // 重点看这里
    );
  }
}

3. 跳转页面

配置完成之后重新编译项目,在项目中调用以下代码就可以实现跳转页面了。

Navigator.pushNamed(context, '/index');

配置路由传参

但是在日常开发中经常需要把参数传到跳转的目标页面中。
很明显上面的配置并不能满足我的需求。

1. 修改routes文件了。

final routes = {
  // 传参
  '/login': (context, {arguments}) => LoginPage(arguments: arguments),
  // 不传参
  '/index': (context) => IndexPage(),
};

//固定写法-路由传参
var onGenerateRoute = (RouteSettings settings) {
  // 统一处理
  final String name = settings.name;
  final Function pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = MaterialPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route =
          MaterialPageRoute(builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
};

2. 页面接受参数

某个页面需要传参,就需要在页面中这样写才能接收到参数,否则arguments就会是null

class LoginPage extends StatefulWidget {
  final Map arguments;
  LoginPage({Key key, this.arguments}) : super(key: key);
  @override
  _LoginPageState createState() => _LoginPageState(arguments: this.arguments);
}

class _LoginPageState extends State<LoginPage> {
  Map arguments;
  _LoginPageState({this.arguments});
  ...
}

3. 跳转页面并传参

以上都配置完成之后,重新编译项目在项目中调用以下代码就能实现路由传参。

Navigator.pushNamed(context, '/login', arguments: {"checkCode": 123456});

配置路由守卫

前端开发过程中,页面跳转时会有路由守卫。而我们的flutter也有同样的功能。

1. 修改 routes 文件

在文件的最下方加入以下代码

//导航的观察者
//导航路由在跳转时的回调,比如 push,pop,remove,replace是,可以拿到当前路由和后面路由的信息
//继承NavigatorObserver
class NewObserver extends NavigatorObserver {
  @override
  void didPush(Route route, Route previousRoute) {
    // 当调用Navigator.push时回调
    super.didPush(route, previousRoute);
    //可通过route.settings获取路由相关内容
    print('跳转到下一个页面');
  }

  @override
  void didPop(Route route, Route previousRoute) {
    
    // 当调用Navigator.pop时回调
    super.didPop(route, previousRoute);
    print('跳回到上一个页面');
  }

  @override
  void didRemove(Route route, Route previousRoute) {
    
    // 当调用Navigator.Remove时回调
    print('调用Navigator.Remove');
    super.didRemove(route, previousRoute);
    
  }
}

2. 配置路由守卫

回到 main.dart 主入口文件

...
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      initialRoute: '/login',
      onGenerateRoute: onGenerateRoute,
      //导航的观察者
      navigatorObservers: <NavigatorObserver>[NewObserver()],
    );
  }
}

最后重新编译项目就完成了我们的需求。

完整代码

1. routes.dart

import "package:flutter/material.dart";

// 全局配置文件
import '../utils/global_config.dart';

import 'package:fushikang_flutter/pages/index_page.dart';
import 'package:fushikang_flutter/pages/login_page.dart';

// 配置路由
final routes = {
  '/login': (context, {arguments}) => LoginPage(arguments: arguments),
  '/index': (context) => IndexPage(),
};

//固定写法-路由传参
var onGenerateRoute = (RouteSettings settings) {
  // 统一处理
  final String name = settings.name;
  final Function pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = MaterialPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route =
          MaterialPageRoute(builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
};

//导航的观察者
//导航路由在跳转时的回调,比如 push,pop,remove,replace是,可以拿到当前路由和后面路由的信息
//继承NavigatorObserver
class NewObserver extends NavigatorObserver {
  @override
  void didPush(Route route, Route previousRoute) {
    // 当调用Navigator.push时回调
    super.didPush(route, previousRoute);
    //可通过route.settings获取路由相关内容
    if (GlobalConfig.isDebug == true) {
      print('跳转到下一个页面');
      print(route);
      print(route.settings);
      print(previousRoute);
      // print(previousRoute);
    }
  }

  @override
  void didPop(Route route, Route previousRoute) {
    
    // 当调用Navigator.pop时回调
    super.didPop(route, previousRoute);
    if (GlobalConfig.isDebug) {
      print('跳回到上一个页面');
      print(route);
      //route.currentResult获取返回内容
      print(previousRoute);
    }
  }

  @override
  void didRemove(Route route, Route previousRoute) {
    
    // 当调用Navigator.Remove时回调
    if (GlobalConfig.isDebug) {
      print('调用Navigator.Remove');
    }

    super.didRemove(route, previousRoute);
    // print(route);
    // print(previousRoute);
  }
}

2. main.dart

import 'dart:io';

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

import 'routes/routes.dart';

void main() {
  runApp(MyApp());
  if (Platform.isAndroid) {
    // 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。
    SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(
      // systemNavigationBarColor: Color(0xFF000000),
      // systemNavigationBarDividerColor: null,
      statusBarColor: Colors.transparent, // 设置状态栏背景显示颜色
      // systemNavigationBarIconBrightness: Brightness.light,
      statusBarIconBrightness:
          Brightness.dark, // 设置状态栏字体显示颜色---(注意只有dark和light两种颜色)
      // statusBarBrightness: Brightness.light,
    );
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

// 获取全局对象
final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      // 是否显示debug
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primaryColor: Colors.orangeAccent),
      initialRoute: '/login',
      onGenerateRoute: onGenerateRoute,
      // 导航的观察者
      navigatorObservers: <NavigatorObserver>[NewObserver()],
      // 配置全局对象
      navigatorKey: navigatorKey,
    );
  }
}

3. global_config.dart

import 'package:flutter/material.dart';

/*
 *系统主题设置,包括系统默认字体 背景色等
 */
class GlobalConfig {
  static bool isDebug = true; //是否是调试模式
  // static String baseUrl = 'http://'; //测试环境
  static String baseUrl = 'http://'; //测试环境
  static bool dark = false;
  static Color fontColor = Colors.black54;
}