Flutter Route (路由) - Fluro

关键字 :FlutterAPP
# Flutter Route (路由) - Fluro

*前言: Flutter 路由跳转有二种方法:一种是用系统原生的跳转方法。第二种是,用第三方框架, 比如 Fluro...*

## Flutter 引入 fluro 库

*官方简介: The brightest, hippest, coolest router for Flutter.*

> 打开 https://pub.dev/packages/fluro 找到最新版本。

### 添加依赖

```dart
dependencies:
fluro: ^1.6.3
```

## 示例项目(官方原文)

在 “example” 文件夹中有一个非常可爱的示例项目。检查出来。否则,继续阅读,直到跑起来。

### 设置

首先,你应该通过初始化来定义一个新的 `Router` 对象:

```dart
final router = Router();
```

对于您来说,全局/静态地存储路由器是很方便的,这样您就可以在应用程序的其他区域访问路由器。

在实例化路由器之后,你需要定义你的 `routes` 和你的 `route handlers`:

```dart
var usersHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
returnUsersScreen(params["id"][0]);
});

void defineRoutes(Router router) {
router.define("/users/:id", handler: usersHandler);

// it is also possible to define the route transition to use
// router.define("users/:id", handler: usersHandler, transitionType: TransitionType.inFromLeft);
}​
 
```

在上面的例子中,路由器会拦截诸如 `/users/1234` 这样的路由,并将应用程序路由到 `UsersScreen` ,将值 `1234` 作为参数传递给那个页面。

### 导航

你可以在 `MaterialApp.onGenerateRoute` 上使用 `Router`。参数通过 `Router.generator` 函数。为此,将函数引用传递给 `onGenerate` 参数,类似于 `onGenerateRoute: router.generator`。

然后你可以使用 `Navigator.push`。然后 flutter 路由机制会为你匹配路由路径。

您也可以自己手动推送到一个路径。像这样做:

```dart
router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);
```

## 实际操作

呃,官方文档可能有点云里雾里的感觉,我们来个实操吧~

### 新建三个文件

- `\routes\Routes.dart` 路由文件
- `\routes\Routes_handler.dart` 路由 handler
- `\routes\fluro_convert_utils.dart` 参数编码转换工具, fluro 不支持中文传参

### 设置路由 (Routes)

在 main 函数里设备路由

```dart
import 'package:fluro/fluro.dart';
import 'package:smarthome/routes/routes.dart';

void main() {
// 设置路由
final router = Router();
Routes.configureRoutes(router);
Routes.router = router;

...
}​
 
```

### 路由入口与配置 (`\routes\Routes.dart`)

这里要做二步

- 定义地址变量, 比如: `static String root = '/';`
- 定义路由 handler, 比如: `router.define(root, handler: appHandler); // 主页`

```dart
///
/// 路由入口
/// 配置路径 Route
///
import 'package:fluro/fluro.dart';
import 'package:flutter/cupertino.dart';
import 'package:smarthome/routes/routes_handler.dart';
import '../main.dart';

class Routes {
/// 路由
staticRouter router;
/// 主页
staticString root = '/';
/// 欢迎页
staticString welcome = '/welcome';
/// 登录页
staticString login = '/login';
/// 注册页
staticString register = '/register';

// 配置route
staticvoidconfigureRoutes(Router router) {
// 未发现对应route
router.notFoundHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
print('route not found!');
return;
});

router.define(root, handler: appHandler); // 主页
router.define(welcome, handler: welcomeHandler); // 欢迎
router.define(login, handler: loginHandler); // 登录
router.define(register, handler: registerHandler); // 注册
}

/// 跳转路由
/// path: 路由地址
/// params: 参数
/// transition: 转场动画
/// replace: 代换
staticFuturepush(BuildContext context, String path, {Map<String, dynamic> params, TransitionType transition = TransitionType.cupertino, bool replace = false, bool clearStack = false}) {
// 对参数进行 encode,解决参数中有特殊字符,影响 fluro 路由匹配
String query = "";
if (params != null) {
int index = 0;
for (var key in params.keys) {
var value = Uri.encodeComponent(params[key]);
if (index == 0) {
query = "?";
} else {
query = query + "\&";
}
query += "$key=$value";
index++;
}
}

// print('navigateTo传递的参数:$query');

path = path + query;
return router.navigateTo(context, path, transition:transition, replace: replace, clearStack: clearStack);
}

/// 返回上一个页面
staticpop() {
// 全局 context
BuildContext context = navigatorKey.currentState.overlay.context;
router.pop(context);
}
}​
 
```

### 路由 handler (`\routes\Routes_handler.dart`)

handler 有二种情况

- 不带参数 直接返回 跳转页面
- 带参数 有中文 做转码跳转。

```dart
import 'package:fluro/fluro.dart';
import 'package:flutter/cupertino.dart';
import 'package:smarthome/routes/fluro_convert_utils.dart';
import 'package:smarthome/views/root.dart';
import 'package:smarthome/views/home/device.dart';
import 'package:smarthome/views/welcome/login.dart';
import 'package:smarthome/views/welcome/register.dart';
import 'package:smarthome/views/welcome/welcome.dart';

/// 主页
var appHandler =
Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
// 不带参数 直接返回 跳转页面
returnRoot();
});

/// 设备
var deviceHandler =
Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {

// 参数没有中文
String device = params['device']?.first;
returnDevice(device: device);
});

/// 选择动作
var selectDoHandler =
Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
String gatewayIdString = params['gatewayId']?.first;
String controlString = params['control']?.first;
int gatewayId = int.parse(gatewayIdString);
if (controlString != null) {
/// 参数有中文, 做转换后 跳转页面
Map<String, dynamic> control = FluroConvertUtils.string2map(controlString);
SelectDo(gatewayId: gatewayId, haveControl: control);
}
returnSelectDo(gatewayId: gatewayId);
});​
```

### fluro 参数编码转换工具 (`\routes\fluro_convert_utils.dart`)

```dart
import 'dart:convert';

/// fluro 参数编码转换工具类
class FluroConvertUtils {
/// fluro 传递中文参数前,先转换,fluro 不支持中文传递
staticStringfluroCnParamsEncode(String originalCn) {
returnjsonEncode(Utf8Encoder().convert(originalCn));
}

/// fluro 传递后取出参数,解析
staticStringfluroCnParamsDecode(String encodeCn) {
var list = List();

///字符串解码
jsonDecode(encodeCn).forEach(list.add);
String value = Utf8Decoder().convert(list);
return value;
}

/// string 转为 int
staticintstring2int(String str) {
returnint.parse(str);
}

/// string 转为 double
staticdoublestring2double(String str) {
returndouble.parse(str);
}

/// string 转为 bool
staticboolstring2bool(String str) {
if (str == 'true') {
returntrue;
} else {
returnfalse;
}
}

/// object 转为 string json
staticStringobject2string(T t) {
returnfluroCnParamsEncode(jsonEncode(t));
}

/// string json 转为 map
staticMap<String, dynamic> string2map(String str) {
return json.decode(fluroCnParamsDecode(str));
}
}​
 
```

### 页面跳转 `Routes.push()`

```dart
Routes.push(context, Routes.addDevice, params: {'gatewayId': gatewayId});​
```

这个是路由封装的方法,直接调用 `push` 就行。

```dart
/// 跳转路由
/// path: 路由地址
/// params: 参数
/// transition: 转场动画
/// replace: 代换
staticFuturepush(BuildContext context, String path, {Map<String, dynamic> params, TransitionType transition = TransitionType.cupertino, bool replace = false, bool clearStack = false}) {
// 对参数进行 encode,解决参数中有特殊字符,影响 fluro 路由匹配
String query = "";
if (params != null) {
int index = 0;
for (var key in params.keys) {
var value = Uri.encodeComponent(params[key]);
if (index == 0) {
query = "?";
} else {
query = query + "\&";
}
query += "$key=$value";
index++;
}
}

// print('navigateTo传递的参数:$query');

path = path + query;
return router.navigateTo(context, path, transition:transition, replace: replace, clearStack: clearStack);
}​


```

### 回到上一页面 `Routes.pop()`

```dart
Routes.pop()
```

pop 方法封装

```dart
/// 返回上一个页面
staticpop() {
// 全局 context
BuildContext context = navigatorKey.currentState.overlay.context;
router.pop(context);
}​
```

这里设置了一个全局 context,如果没有设置,直接把 context 传入就行了。

比如:

```dart
staticpop(BuildContext context) {
router.pop(context);
}​
```

### 取得全局 Context

有时,我们要在网络工具类做弹框处理或页面跳转,比如没有登录时,要跳转到登录页面,但是网络工具类不是 `Widget`,没有 `Context`, 所以做不了跳转,这时,我们就要一个全局 Context..

#### main 文件配置 Context

```dart
/// 定义全局 navigatorKey
/// 全局 context
/// BuildContext context = navigatorKey.currentState.overlay.context;
/// 路由跳转
/// navigatorKey.currentState.pushNamed('/');
final GlobalKey navigatorKey = new GlobalKey();

class App extends StatelessWidget {
// This widget is the root of your application.
@override
Widgetbuild(BuildContext context) {
returnMaterialApp(
title: 'ATU 智能家居',
debugShowCheckedModeBanner: Global.isDebug,
// 配置路由
onGenerateRoute: Routes.router.generator,
// 全局配置
navigatorKey: navigatorKey,
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Global.themeColor,
),
darkTheme: ThemeData.dark(),
home: Root(),
);
}
}​
```

#### 全局 Context 调用

```dart
/// 全局 context
BuildContext context = navigatorKey.currentState.overlay.context;​
```

## **参考资料**:

Fluro (https://pub.dev/packages/fluro )

Flutter - 路由管理 - 02 - Fluro (https://juejin.im/post/6844903866262093837#heading-21)

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论