# Flutter教程 - 6 路由

什么是路由?

其实就是页面跳转。

Flutter 中的路由系统基于导航栈来管理不同页面的顺序和状态。

什么是导航栈?

导航栈(Navigation Stack)是在应用程序中用于管理页面或路由的一种数据结构。它类似于堆栈(Stack)数据结构,遵循先进后出(LIFO)的原则。

在 Flutter 中,导航栈用于存储打开的页面或路由,每当你打开一个新的页面或路由时,它会被推入(push)到导航栈的顶部。因为系统当前显示的页面就是当前在导航栈顶的的页面。当你执行返回操作时,最顶部的页面会被弹出(pop)出栈,回到上一个页面。

在 Flutter 中,Navigator 类负责管理导航栈,并提供了管理堆栈的方法。你可以使用 Navigator 的方法来推入新页面、弹出当前页面、查看当前栈中的页面等。导航栈在应用程序中起着重要的作用,它允许你实现页面之间的流畅切换、返回操作以及状态管理。

以下是 Navigator 类提供的一些常用的方法,了解一下,后面逐一介绍一下如何使用。

  • 将新页面推入导航栈,实现页面切换。
Navigator.push(context, MaterialPageRoute(builder: (context) => NewPage()));
1
  • 将当前页面弹出导航栈,返回上一个页面。
Navigator.pop(context);
1
  • 替换当前页面为新页面,从而实现页面切换并且移除当前页面。
Navigator.pushReplacementNamed(context, "/message");
1
  • 将导航栈中的页面依次弹出,直到某个指定页面。
Navigator.popUntil(context, ModalRoute.withName('/home'));
1
  • 检查是否可以执行返回操作(即是否还有页面可以弹出)。
Navigator.canPop(context)
1

Flutter 中给我们提供了两种配置路由跳转的方式:

  • 基本路由
  • 命名路由

下面学习一下两种路由的使用,以及如何使用 Navigator 类提供的方法进行页面的跳转。

# 6.1 基本路由

下面实现一个从一个页面跳转到另一个页面,并返回的功能,并可以根据需要传递参数。

# 1 页面跳转

首先准备好两个页面,这里分别是 main.dartsearch.dart

main.dart

main.dart 中添加一个按钮,点击按钮,跳转到 search.dart页面。

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

void main() => runApp(const MyApp());

/// App根Widget
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MainPage(),
    );
  }
}

/// 主页
class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("主页"),
      ),
      body: Center(
        	// --------------添加一个按钮-----------------
          child: ElevatedButton(
              onPressed: () {
                // 点击按钮,跳转到search页面
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return const SearchPage();
                }));
              },
              child: const Text("跳转到search")
          )
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

首先在 main.dart 中引入 search.dart,在按钮的点击事件中,通过 Navigator.push 方法跳转到 SearchPage 页面Navigator.push 接收两个参数,一个是上下文对象,一个是路由对象。路由对象接收一个参数 builder 是一个函数,在函数中返回要跳转到的新的页面 Widget

这里页可以使用箭头函数来写:

// 点击按钮,跳转到search页面
Navigator.push(context, MaterialPageRoute(builder: (context) => const SearchPage()));
1
2

search.dart

search.dart 页面很简单,就是使用 Scaffold 创建了一个简单的页面。

import 'package:flutter/material.dart';

/// 搜索页面
class SearchPage extends StatefulWidget {
  const SearchPage({Key? key}) : super(key: key);

  
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("搜索"),
      ),
      body: const Center(
        child: Text("搜索页面"),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

显示效果,当点击 跳转到search 按钮的时候,会跳转到搜索页面。

# 2 跳转传递参数

刚才在进行页面跳转的时候,没有传递参数,现在演示一下从 main.dart 跳转到 search.dart,并传递参数。

传递参数是很简单的,因为 SearchPage 有构造函数,只需要传递参数给构造函数即可,在 SearchPage 中就可以拿到参数了。

search.dart

import 'package:flutter/material.dart';

/// 搜索页面
class SearchPage extends StatefulWidget {

  final String content;

  // ----- 通过构造函数接收参数
  const SearchPage({Key? key, required this.content}) : super(key: key);

  
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("搜索"),
      ),
      body: Center(
        // ----- 将接收到的参数显示出来
        child: Text(widget.content),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

SearchPage 中通过构造方法接收传递参数,在 _SearchPageState 中获取参数需要通过 widget.属性 的方式获取。

main.dart

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

void main() => runApp(const MyApp());

/// App根Widget
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MainPage(),
    );
  }
}

/// 主页
class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("主页"),
      ),
      body: Center(
          child: ElevatedButton(
              onPressed: () {
                // ----- 创建SearchPage的时候传递参数
                Navigator.push(context, MaterialPageRoute(builder: (context) => const SearchPage(content: "你好,逗比")));
              },
              child: const Text("跳转到search")
          )
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

在创建 SearchPage 的时候,传递参数即可。

# 3 页面返回

main.dart 跳转到 search.dart,如何返回呢?

从一个页面跳转到下一个页面,默认情况下,下一个页面的左上角会显示一个返回按钮,这个时候,点击返回按钮就可以直接返回了。

但是有些时候,我们不想使用返回按钮,而是主动去触发返回,那么就需要使用 Navigator.pop 来返回了。

修改 search.dart

import 'package:flutter/material.dart';

/// 搜索页面
class SearchPage extends StatefulWidget {

  final String content;

  const SearchPage({Key? key, required this.content}) : super(key: key);

  
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("搜索"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(widget.content),
            const SizedBox(height: 40),
            ElevatedButton(
                onPressed: () {
                  // ----- 返回到上一个页面
                  Navigator.pop(context);
                },
                child: const Text("返回")
            )
          ],
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

在当前页面,返回上一个页面,只需要调用 Navigator.pop(context) ,就可以在当前的栈中弹出当前页面,返回到上一个页面。

# 6.2 命名路由

前面介绍了基本路由的使用。但是如果应用页面很多,使用基本路由会很不方便,一个是写法不方便,另外就是不好统一管理,每个用到跳转的地方都需要引入跳转的页面。

下面介绍命名路由的使用,很好的的解决了上面的问题。

首先新建三个页面 HomePageSearchPageMessagePage (页面代码在后面)。

然后实现在 HomePage 中通过按钮分别跳转到SearchPageMessagePage 页面。

# 1 配置路由

在使用命名路由之前,需要统一配置路由。命令路由的配置是在 MaterialApp 中的。

代码如下:

main.dart

import 'package:flutter/material.dart';
// 1.引入所有的页面
import './pages/home.dart';
import './pages/search.dart';
import './pages/message.dart';

void main() => runApp(const MyApp());

/// App根Widget
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        // ---- 3.初始化路由,初始化进入的页面
        initialRoute: "/",
        // ---- 2.所有的路由统一配置到这里
        routes: {
          '/': (context) => const HomePage(),
          '/search': (context) => const SearchPage(),
          '/message': (context) => const MessagePage(),
        });
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  1. 首先将 MaterialApp 中的 home 属性去掉;
  2. main.dart 中引入所有的页面的页面;
  3. MaterialApp 组件中,使用 routes属性配置所有的路由,routes 是一个 map 类型,value 是一个函数;
  4. 还需要使用 initialRoute 属性配置初始化的路由。上面初始化的路由是 "/" , 表示初始化的页面是 HomePage

下面展示一下 SearchPage 、MessagePage 页面的内容:

search.dart

页面非常简单,只有一个返回按钮,用于返回。

import 'package:flutter/material.dart';

/// 搜索页面
class SearchPage extends StatefulWidget {

  const SearchPage({Key? key}) : super(key: key);

  
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("搜索"),
      ),
      body: Center(
        child: ElevatedButton(
            onPressed: () {
              // ----- 返回到上一个页面
              Navigator.pop(context);
            },
            child: const Text("返回")
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

message.dart

页面非常简单,只有一个返回按钮,用于返回。

import 'package:flutter/material.dart';

class MessagePage extends StatefulWidget {
  const MessagePage({Key? key}) : super(key: key);

  
  State<MessagePage> createState() => _MessagePageState();
}

class _MessagePageState extends State<MessagePage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("消息"),
      ),
      body: Center(
        child: ElevatedButton(
            onPressed: () {
              // ----- 返回到上一个页面
              Navigator.pop(context);
            },
            child: const Text("返回")
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 2 页面跳转

HomePage 中通过按钮分别跳转到SearchPageMessagePage 页面,下面看一下 home.dart 的代码,也是非常的简单。

home.dart

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("主页"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () {
                  // ----- 跳转到search页面
                  Navigator.pushNamed(context, "/search");
                },
                child: const Text("跳转到search")
            ),
            const SizedBox(height: 40),
            ElevatedButton(
                onPressed: () {
                  // ----- 跳转到message页面
                  Navigator.pushNamed(context, "/message");
                },
                child: const Text("跳转到message")
            )
          ],
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

直接就是在页面上添加了两个按钮,点击按钮分别跳转到响应的页面。

跳转的时候使用 Navigator.pushNamed() 方法来跳转,第一个参数是上下文对象,第二个参数直接写在 MaterialApp 中配置的路由的名字即可。无需引入页面,在哪里都可以用,直接就可以跳转,灰常的方便。

# 3 传递参数

传递参数要稍微复杂一些。

下面实现跳转到搜索页面传递参数。

主要分为三步:

  • 接收参数配置
  • 路由配置
  • 跳转传递参数

接收参数

搜索页面接收参数,所以这里我们先修改 SearchPage ,修改构造函数,接收参数。

import 'package:flutter/material.dart';

/// 搜索页面
class SearchPage extends StatefulWidget {

  final Map arguments;
	// ---- 使用 arguments 接收参数
  const SearchPage({Key? key, required this.arguments}) : super(key: key);

  
  State<SearchPage> createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("搜索"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(widget.arguments["content"]),
            const SizedBox(height: 40),
            ElevatedButton(
                onPressed: () {
                  // ----- 返回到上一个页面
                  Navigator.pop(context);
                },
                child: const Text("返回")
            )
          ],
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

在上面的代码中,定义了一个 Map 类型的成员变量,用于接收参数。

路由配置

首先在 MaterialApp 中去掉 routes 属性,然后添加 onGenerateRoute 属性。onGenerateRoute 接收的是一个函数,先按照下面的固定写法写就好了。将路由配置提取成一个变量,在 onGenerateRoute 中会用到。

import 'package:flutter/material.dart';
import './pages/home.dart';
import './pages/search.dart';
import './pages/message.dart';

void main() => runApp(const MyApp());

// 1、定义Map类型的routes
final Map routes = {
  '/': (context) => const HomePage(),
  '/search': (context, {arguments}) => SearchPage(arguments: arguments),
  '/message': (context) => const MessagePage(),
};

/// App根Widget
class MyApp extends StatelessWidget {

  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      // 初始化路由,初始化进入的页面
      initialRoute: "/",
      
      // 2、调用onGenerateRoute处理
      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;
          }
        }
        return null;
      },
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

在上面的代码中提取了 routes 变量,因为跳转到 SearchPage 页面携带参数,所以在路由配置中,在函数中配置了一个命名参数 arguments,并将 arguments 传递给了 SearchPage 页面。

上面的流程看起来比较闷逼,待会再解释。

跳转传递参数

现在从 HomePage 跳转到 SearchPage 传递参数,

传递参数很简单,只需要在 HomePage 跳转的时候,通过 arguments 参数传递参数即可。

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("主页"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () {
                  // ----- 跳转到search页面,传递参数
                  Navigator.pushNamed(context, "/search", arguments: {"content":"你好,逗比"});
                },
                child: const Text("跳转到search")
            ),
            const SizedBox(height: 40),
            ElevatedButton(
                onPressed: () {
                  // ----- 跳转到message页面
                  Navigator.pushNamed(context, "/message");
                },
                child: const Text("跳转到message")
            )
          ],
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 4 传递参数流程

  1. 首先在跳转的时候使用 Navigator.pushNamed 跳转并传递了参数;
  2. 跳转会调用 onGenerateRoute 配置的函数。
(RouteSettings settings) {
  	// name 这里会拿到路由的名称,也就是/search
    final String? name = settings.name;			
  	// 通过/search,在路由配置字典中拿到对应的函数(context, {arguments}) => SearchPage(arguments: arguments)。
    final Function? pageContentBuilder = routes[name];		
    if (pageContentBuilder != null) {
      // 查看跳转有没有携带参数
      if (settings.arguments != null) {
        // 如果携带了参数,则调用路由配置中对应的函数,将参数传递进去,也就是调用了SearchPage中的构造函数,最终创建了路由对象
        final Route route = MaterialPageRoute(
            builder: (context) =>
                pageContentBuilder(context, arguments: settings.arguments));
        return route;
      } else {
        // 如果跳转没有携带参数,调用pageContentBuilder不带参数
        final Route route = MaterialPageRoute(
            builder: (context) => pageContentBuilder(context));
        return route;
      }
    }
    return null;
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

路由跳转都会走 onGenerateRoute 函数,所以如果要进行一些拦截操作,可以在 onGenerateRoute 中进行处理。

  1. SearchPage 接收到参数。

# 5 重构代码

在上面的代码中,我们在 main.dart 中将路由配置定位为一个 Map 对象,其实这样代码混乱不利于管理,我们可以将路由配置和onGenerateRoute,抽离到一个单独的文件。

例如,新建一个 router.dart,代码如下:

首先引入路由的各个页面文件,然后定义路由配置和 onGenerateRoute 函数。

import 'package:flutter/material.dart';
import '../pages/home.dart';
import '../pages/search.dart';
import '../pages/message.dart';

// 1、定义Map类型的routes
final Map routes = {
  '/': (context) => const HomePage(),
  '/search': (context, {arguments}) => SearchPage(arguments: arguments),
  '/message': (context) => const MessagePage(),
};

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;
    }
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

重新修改 main.dart

import 'package:flutter/material.dart';
// 引入路由配置
import './router/router.dart';

void main() => runApp(const MyApp());

/// App根Widget
class MyApp extends StatelessWidget {

  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      // 初始化路由,初始化进入的页面
      initialRoute: "/",
      // onGenerateRoute处理
      onGenerateRoute: onGenerateRoute,
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

代码结构就很清晰了,也显得很简洁了。

# 6.3 替换路由

如果从 HomePage 页面跳转 SearchPage 页面,从 SearchPage 页面跳转到 MessagePage 页面,在 MessagePage 页面点击返回,如何能返回到 HomePage 页面呢?

在 MessagePage 页面通过 Navigator.pop(context); 直接返回 HomePage 页面。

这里只需要在 SearchPage 通过 Navigator.pushReplacementNamed() 方法跳转到 MessagePage 页面接口,MessagePage 会替换掉栈顶的 SearchPage 页面。

// 在 SearchPage 页面跳转到 MessagePage
Navigator.pushReplacementNamed(context, '/message');
1
2

这样在 MessagePage 页面返回的时候,会直接返回到 HomePage 页面。

# 6.4 返回根路由

如果现在的导航栈是下面的这样的情况,该如何跳转到根路由的首页呢?

我们可以使用 Navigator.pushNamedAndRemoveUntil() 方法,它用于实现页面导航并清除导航栈中的页面,以达到指定条件的效果。具体而言,它的作用如下:

  1. 首先,它会压入(导航到)一个新的命名路由页面到导航栈。
  2. 压入新页面之前,它会从导航栈中删除所有指定条件之前的页面,以确保只剩下符合条件的页面。
// ----- 返回首页
Navigator.pushNamedAndRemoveUntil(
  context,
  '/', // 跳转到的页面名称
  (route) => false, // 始终返回false,表示一直删除,删除所有页面
);
1
2
3
4
5
6

上面的代码会跳转到 "/" 首页,第三个参数是一个回调函数,用于确定是否删除页面。当返回 true 时,删除停止,页面保留在导航栈中。上面一直返回false,则会清空导航栈。

再举一个例子:

/ 跳转到 /a,从 /a 跳转到 /b ,从 /b 跳转到 /d ,在 /d 中如何返回 /a,在 /a 通过 Navigator.pop 返回到 /,那么在 /d 中该如何返回到 /a 呢?

Navigator.pushNamedAndRemoveUntil(
  context,
  '/a', // 返回到/a页面
  ModalRoute.withName('/'), // 删除中间的页面,直到根页面
);
1
2
3
4
5

# 6.5 页面切换风格

我们之前使用的风格是 Material 库的风格,Material 组件库中路由的切换是通过 MaterialPageRoute 组件实现的,MaterialPageRoute 组件会根据 AndroidiOS 上显示不同的风格。例如在切换页面的时候,在 Android 上是上下滑动切换,iOS 是左右滑动切换。

如果想在 Android 上实现和 iOS 上一样的切换效果,可以使用 Cupertino 库,其中 CupertinoPageRouteCupertino 组件库提供的iOS 风格的路由切换组件。

所以修改之前的路由配置即可,也是很简单的,需要修改两个地方:

  1. 引入 cupertino.dart,删除 material.dart
  2. MaterialPageRoute 替换为 CupertinoPageRoute
// 1.配置iOS分隔的路由,删掉material.dart,引入cupertino.dart
import 'package:flutter/cupertino.dart';
// import 'package:flutter/material.dart';
import '../pages/home.dart';
import '../pages/search.dart';
import '../pages/message.dart';

// 1、定义Map类型的routes
final Map routes = {
  '/': (context) => const HomePage(),
  '/search': (context, {arguments}) => SearchPage(arguments: arguments),
  '/message': (context) => const MessagePage(),
};

var onGenerateRoute = (RouteSettings settings) {
  // 统一处理
  final String? name = settings.name;
  final Function? pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      // 2. 将MaterialPageRoute替换为
      final Route route = CupertinoPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route = CupertinoPageRoute(
          builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33