6

Flutter 自身是提供了 Navigator widget 来实现应用的路由功能。但使用一些路由插件,可以帮助我们更方便快捷的实现 Flutter 应用页面间的跳转和传值等功能。

这篇笔记我们主要来学习一下 fluro 这个插件。

1. 项目引入 fluro

Flutter 应用中要使用任何第三方插件,都需要先在项目中进行引入。

打开项目根目录中的 pubspec.yaml 文件,在 dependencies 属性下面添加 fluro 的配置代码:

dependencies:
  fluro: ^1.6.3

参考代码截图如下:

image.png

说明:1.6.3 是当前(2020.04.13)fluro 的最新版本号,大家以后在使用时,建议先去官网看看最新的版本号是多少,配置的时候就改成最新版本号即可。

2. fluro 的基本使用

fluro 最基本的功能就是“跳转页面”,其他的“传值”、“返回”等功能对于我们菜鸡来说都是高级操作了,所以先不谈。我们先来学基操!

2.1 建立路由文件

一般情况下,我们都会在项目的 lib 目录中创建一个的新的文件夹(例如:lib/routers),专门用来存放与路由相关的配置代码。

2.2 路由配置

创建一个 lib/routers/routes.dart 文件用来进行路由的相关配置:

import 'package:flutter/material.dart';
// 引入 fluro
import 'package:fluro/fluro.dart';
// 引入路由要跳转的页面文件
import 'package:flutter_fluro_demo/home_page.dart';
import 'package:flutter_fluro_demo/login_page.dart';

class Routes {
  // 各个页面的路径字符串
  static String home = '/home';
  static String login = '/login';
  // 创建一个 configureRoutes 方法,用于路由配置
  static void configureRoutes(Router router) {
    // 配置 home 首页路由
    router.define(home, handler: Handler(
        handlerFunc: (BuildContext context, Map<String, List<String>> params) {
          return HomePage();
        },
      ),
    );
    // 配置 login 登录页路由
    router.define(login, handler: Handler(
        handlerFunc: (BuildContext context, Map<String, List<String>> params) {
          return LoginPage();
        }
      ),
    );
  }
}

在这个配置文件里,我们以“首页”和“登录页”为例,做了一个最基础的路由配置。

2.3 路由静态化处理

为了方便我们后面在各个页面中使用路由,我建议(官方也建议)先对路由做一个静态化处理。

lib/routers 中再创建一个 application.dart 文件,添加以下代码:

import 'package:fluro/fluro.dart';

class Application {
  static Router router;
}

在这段代码中,我们创建了一个 Application 对象,并设置了一个静态属性 router。

在下一步全局注入路由的时候,我们会把调用 Router() 方法得到的路由对象保存在 Application.router 属性中。这样,在后续各个页面中使用路由时,就可以直接通过 Application.router 来拿到路由对象,而不需要反复调用 Router() 方法了。

2.4 全局注入路由

各项配置完成之后,接下来就需要在项目入口文件 main.dart 中注入路由来使我们的路由生效。

import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter_fluro_demo/routers/routes.dart'; // 路由配置文件
import 'package:flutter_fluro_demo/routers/application.dart';  // 路由静态化文件

void main() {
  final router = Router();  // 获取路由对象
  Routes.configureRoutes(router);  // 调用路由配置方法
  Application.router = router;  // 将路由对象静态化
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateRoute: Application.router.generator,  // 将路由配置到 MaterialApp 中
      // ...
    );
  }
}

2.5 路由跳转

fluro 中最简单的跳转方式就是通过 navigateTo() 方法来实现:

import 'package:flutter_fluro_demo/routers/application.dart';
// ...
Application.router.navigateTo(context, '/home');

参考代码截图如下:

image.png
到这一步,我们一个最简单的路由跳转就实现啦。

3. fluro 的进阶使用

路由的基本使用学会了之后,接下来我们就需要增加一丢丢的难度了。

3.1 拆分路由配置文件

在前面的路由基础用法里,我们将所有关于路由的配置都放在了 routes.dart 文件中,当我们项目的页面逐渐增多时,就会导致这个文件变得越来越大,代码越来越多,后期维护起来也会越来越不方便。

所以,我们要对 routes.dart 文件中的代码进行拆分。

routes.dart 原本的代码如下:

image.png

从图中代码可以看到,路由操作的大部分代码都集中在了 handler 属性中,因此,我们就把每一个 handler 属性的属性值都提取出去。

lib/routers 中再创建一个文件:route_handlers.dart,将拆分出来的代码放进去:

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

import 'package:flutter_fluro_demo/home_page.dart';
import 'package:flutter_fluro_demo/login_page.dart';

Handler homeHandler = Handler(
  handlerFunc: (BuildContext context, Map<String, List<String>> params) {
    return HomePage();
  },
);

Handler loginHandler = Handler(
  handlerFunc: (BuildContext context, Map<String, List<String>> params) {
    return LoginPage();
  },
);

这样拆分后,我们原本的 routes.dart 文件就变得很干净了。

import 'package:fluro/fluro.dart';
import './route_handlers.dart';

class Routes {
  static String home = '/home';
  static String login = '/login';

  static void configureRoutes(Router router) {
    router.define(home, handler: homeHandler);
    router.define(login, handler: loginHandler);
  }
}

3.2 路由传参

虽然我们把路由传参划分到了进阶用法里,但是实际上我们应该都清楚,任何一个 App 里,路由传参功能都是必不可少的。更何况,fluro 的路由传参其实 so easy~

路由传参其实简单理解为一个点外卖的过程。例如我们要将 home 页面的数据传递 detail 页面,那么 home 页面就是商家,detial 页面就是整天宅在家里扣 jio 的你,而 fluro,就是我们的外卖骑手。

理解了传参的流程之后,接下来我们就可以开始搬砖了。

第一步:在 detial 页面配置要接收的参数

detail 页面中的代码如下:

import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {
  DetailPage({this.detailId});
  final String detailId;

  //...
}

这里我们定义了一个 detailId,用来接收后面 home 传递过来的参数。

我的案例代码截图如下:

image.png

第二步:在 home 页面设置要传递的参数

home 页面的路由跳转和传参代码如下:

RaisedButton(
  child: Text('去详情页'),
  onPressed: () {
    Application.router.navigateTo(context, '/detail/001');
  },
),

/detail/001 中的 /detail 就是我们要去到的 detail 页面的路径,001 就是我们要传递给 detail 页面的参数。

第三步:在路由配置文件中对 detail 路由进行配置

打开 lib/routers/routes.dart 文件,对 detail 的路由进行如下配置:

class Routes {
  // ...
  static String detail = '/detail/:id';

  static void configureRoutes(Router router) {
    // ...
    router.define(detail, handler: detailHandler);
  }
}

参考代码截图如下:

image.png

detailHandler 报错是因为我们还没创建这个变量,下一步创建好就不会报错了。)

/detail/:id 中的 id 是我们自己定义的一个参数名,是对 home 页面传递的参数进行命名。

接下来,再打开 lib/routers/routes_handlers.dart 文件,配置 detail 的 handler 方法。

import 'package:flutter_fluro_demo/detail_page.dart';
// ...
Handler detailHandler = Handler(
  handlerFunc: (BuildContext context, Map<String, List<String>> params) {
    String id = params['id'].first; // 通过 params 获取到路由中传递的参数
    return DetailPage(detailId: id);
  },
);

到此,我们 home 页面,通过路由往 detail 页面的传参就已经完成了。

image.png

3.3 返回页面

在 Flutter 中,跳转后的页面左上角会自带一个返回箭头,但是有的时候,我们也需要点击界面其他地方来实现页面的返回,又或者,我们想返回到一个指定的界面。

3.3.1 返回到上一页面

页面返回的代码很简单:

RaisedButton(
  child: Text('返回上一页'),
  onPressed: () {
    // flutter 
    Navigator.pop(context);
    // fluro
    // Application.router.pop(context);
  },
)

从上面代码可以看出,实现“返回上一页面”功能的方式两种:一种是 flutter 自带的 Navigator widget 提供的 pop 方法;另一种是 fluro 中提供的 pop 方法。

这里我们列出 flutter 原生的返回方式,是因为 flutter 原生的方式更简洁一些,所以路由的返回功能我们更多会选择直接用 Navigator 的方法返回。

3.3.2 返回到指定页面

fluro 中并没有提供专门的“返回到指定页面”的方法(我有看 fluro 的源码,确实没有找到,如果这里说法有误请大家评论里告诉我)。所以如果我们想要实现“返回到指定页面”的效果,可以直接用 navigateTo 页面跳转方法实现。

具体代码可以参考前面「2.5 路由跳转」的示例代码。

3.4 管理历史记录

默认情况下,每一次的路由跳转,都会有一个新的路由记录注册到路由表中。

fluro 中的 navigateTo() 方法可以设置第三个参数来管理路由历史记录。

3.4.1 替换历史记录

替换历史记录是指用“跳转后的新页面”记录替换掉“当前页面”记录。将 navigateTo() 方法的第三个参数设置为 replace: true 即可。

child: RaisedButton(
  child: Text('去详情页'),
  onPressed: () {
    Application.router.navigateTo(context, '/detail/001', replace: true);
  },
),

参考代码截图如下:

image.png

当我们从“登录页”跳转到“首页”,再从“首页”跳转到“详情页”,然后点击“详情页”左上角的返回按钮,可以发现,直接返回到了“登录页”。因为我们的历史记录里面已经没有保留“首页”的记录了。

3.4.2 清空历史记录

除了替换一条历史记录外,navigateTo() 方法还可以将第三个参数设置为 clearStack: true 来实现清空历史记录的效果。

child: RaisedButton(
  child: Text('去详情页'),
  onPressed: () {
    Application.router.navigateTo(context, '/detail/001', clearStack: true);
  },
),

4. 最后

fluro 的用法大概就是这些了,如果还有没写到的知识点,大家可以在评论里告诉我,我再补充。


有猫饼
66 声望3 粉丝