Flutter中封装Fluro路由配置,以及无context跳转与传参

fluro路由简单配置

  • 引入fluro

pubspec.yaml

yml 复制代码
dependencies:
	# 路由管理
  fluro: ^2.0.5

一、封装fluro路由

  • 主要初始化路由表信息,以及找不到页面时默认返回404页面

lib/router/routes.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/pages/home/router/router_test_page.dart';
import 'package:planx_app/pages/index_page.dart';
import 'package:planx_app/widget/empty.dart';

class Routes {
  static FluroRouter router = FluroRouter();
  // 设置页面
  // 页面信息
  static String indexPage = "/";
  // 路由测试页面
  static String routerPage = "/routerTest";

  // 初始化,配置路由表
  static _initRouter() {
    // 首页
    router.define(indexPage,
        handler: Handler(handlerFunc: (_, __) => const IndexPage()));
    // 路由测试页面
    router.define(routerPage,
        handler: Handler(handlerFunc: (_, __) => const RouterTestPage()));
  }

  // 配置路由
  static void configureRoutes() {
    router.notFoundHandler = Handler(handlerFunc: (_, __) {
      // 找不到路由时,返回404页面
      return Scaffold(
          appBar: AppBar(),
          // 这是自行封装的Empty组件
          body: const Center(child: Empty(type: EmptyType.page404)));
    });
    // 初始化路由信息
    _initRouter();
  }
}

main.dart 中初始化与配置路由

dart 复制代码
import 'package:planx_app/router/routes.dart';

void main() async {
	// ...
  // 注册路由
  Routes.configureRoutes();
  runApp(const MyApp());
}
// ....
// MaterialApp中配置路由
MaterialApp(
  // ...
  // 配置路由
  onGenerateRoute: Routes.router.generator,
);

二、封装页面跳转的方法

  • flutter中可以直接使用Navigator进行路由调整,为了统一建议还是先封装一下
  • 这里只是简单的封装,在后面还有介绍关于无context跳转,以及特殊参数传递的封装

lib/router/navigator_util.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

class NavigatorUtil {
  static void push(
    BuildContext context,
    String path, {
    bool replace = false, // 替换当前页面
    bool clearStack = false,  // 是否清空路由栈
    Object? arguments,
    TransitionType? transition,  // 页面进入动效
  }) {
    Routes.router.navigateTo(
      context,
      path,
      replace: replace,
      clearStack: clearStack,
      // 页面进入从右侧进入
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }
}

使用

dart 复制代码
 ElevatedButton(
  onPressed: () {
    NavigatorUtil.push(context, Routes.routerPage);
  },
  child: const Text("跳转路由测试页面"),
),

效果:

无context跳转

有些时候我们可能不会在builder中跳转路由,所以没有context

  • 在MaterialApp中有一个navigatorKey属性,指定navigatorKey后就可以直接操作Navigator,不需要使用context

重新封装路由跳转方法

lib/router/navigator_util.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

class NavigatorUtil {
  // 无context跳转
  static void push(
    String path, {
    bool replace = false,
    bool clearStack = false,
    Object? arguments,
    TransitionType? transition,
  }) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context replase
  static void replase(String path,
      {bool replace = true, bool clearStack = false, Object? arguments}) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context,清空路由栈跳转,一般用于跳转首页这种情况
  static void switchTab(String path,
      {bool replace = false, bool clearStack = true, Object? arguments}) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
  static void back({int count = 1, Object? params}) {
    NavigatorState state = Navigator.of(navigatorKey.currentContext!);
    while (count-- > 0) {
      state = state..pop(params);
    }
  }
}

main.dart 配置

dart 复制代码
import 'package:planx_app/router/navigator_util.dart';
import 'package:planx_app/router/routes.dart';
// ...
MaterialApp(
  // ...
  // 配置路由
  onGenerateRoute: Routes.router.generator,
  // 指定路由的全局key
  navigatorKey: navigatorKey,
);

使用

dart 复制代码
NavigatorUtil.push(Routes.routerPage);

传递参数

一、传递params参数

  • 新建路由接收参数页面

router_params_page.dart

dart 复制代码
class RouterParamsPage extends StatelessWidget {
  const RouterParamsPage({Key? key, required this.content}) : super(key: key);
  // 用来接收路由传递过来的参数
  final String content;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //....
      body: Center(
        child: Text(content), // 将参数显示到页面
      ),
    );
  }
}
  • 配置路由

lib/router/routes.dart

dart 复制代码
class Routes {
	//...
  // 路由传递参数页面
  static String routerParamPage = "/routerParam";
  static _initRouter() {
    // ...
    // 路由传递参数页面
    router.define(routerParamPage,
        handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
      // 获取路由参数
      String routerParam = params["content"]?[0];
      return RouterParamsPage(content: routerParam);
    }));
  }
	// ...
}

使用:路由跳转

  • 相当于直接在url后面拼接参数
dart 复制代码
// 传递参数
NavigatorUtil.push('${Routes.routerParamPage}?content=params11111');

参数带有特殊字符和中文时无法接收(比如: "www.baidu.com")

  • 这种情况需要考虑进行encode这样保证参数正常
  • 且通过上述的方法传递参数,每次都要拼接,并不优雅,我们顺便进行改造一下
改造NavigatorUtil方法,加密参数
  • 以下封装是完整版本

lib/router/navigator_util.dart 加密

dart 复制代码
import 'dart:convert';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

class NavigatorUtil {
  // 这里进行加密
  // 处理url参数拼接
  static String _getPathParams({Map<String, String>? params, path}) {
    if (params != null) {
      // Utf8Encoder,解决参数有特殊字符,中文不能传递的情况
      String p = params.entries
          .map((e) =>
              '${e.key}=${jsonEncode(const Utf8Encoder().convert(e.value))}')
          .join('&');
      path = '$path?$p';
    }
    return path;
  }

  // 无context跳转
  static void push(
    String path, {
    Map<String, String>? params,
    bool replace = false,
    bool clearStack = false,
    Object? arguments,
    TransitionType? transition,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context replase
  static void replase(
    String path, {
    Map<String, String>? params,
    bool replace = true,
    bool clearStack = false,
    Object? arguments,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context,清空路由栈跳转,一般用于跳转首页这种情况
  static void switchTab(
    String path, {
    Map<String, String>? params,
    bool replace = false,
    bool clearStack = true,
    Object? arguments,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
  static void back({int count = 1, Object? arguments}) {
    NavigatorState state = Navigator.of(navigatorKey.currentContext!);
    while (count-- > 0) {
      state = state..pop(arguments);
    }
  }
}
解码
  • 在路由定义位置解码

lib/router/routes.dart

dart 复制代码
  // 路由传递参数页面
    router.define(routerParamPage,
        handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
      // 获取路由参数
      String routerParam = _decodeParams(params["content"]?[0]);
      return RouterParamsPage(content: routerParam);
    }));

//...
  ///字符串解码,中文不能传递等问题
  static _decodeParams(String params) {
    List<int> list = [];
    jsonDecode(params).forEach(list.add);
    return const Utf8Decoder().convert(list);
  }

使用:

dart 复制代码
// 传递参数
NavigatorUtil.push(Routes.routerParamPage, params: {"content": "https://www.bd的收费吗,是打开就好aidu.com"});

二、传递类实例参数

  • 使用上面的NavigatorUtil方法,我们已经可以传递类参数了

使用页面:

dart 复制代码
// 传递参数,arguments可以接收一个类作为参数,Person是自己定义的类
NavigatorUtil.push(Routes.routerInstancePage,arguments: Person(name: "terry", age: 40));

接收,需要在build中接收

dart 复制代码
Widget build(BuildContext context) {
  // 接收参数
  Person p = (ModalRoute.of(context)?.settings.arguments as Person);
  return Scaffold(
    appBar: AppBar(title: Text('路由传递类参数')),
    body: Center(
      child: Column(
        children: [
          Text('ddd'),
          Text('姓名${p.name}'),
          Text('年龄${p.age}'),
        ],
      )),
  );
}
相关推荐
zhanghaisong_20151 分钟前
Caused by: org.attoparser.ParseException:
前端·javascript·html·thymeleaf
Eric_见嘉4 分钟前
真的能无限试(白)用(嫖)cursor 吗?
前端·visual studio code
DK七七34 分钟前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
老赵的博客1 小时前
QSS 设置bug
前端·bug·音视频
Chikaoya1 小时前
项目中用户数据获取遇到bug
前端·typescript·vue·bug
南城夏季1 小时前
蓝领招聘二期笔记
前端·javascript·笔记
Huazie1 小时前
来花个几分钟,轻松掌握 Hexo Diversity 主题配置内容
前端·javascript·hexo
NoloveisGod1 小时前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing1 小时前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
海上彼尚2 小时前
实现3D热力图
前端·javascript·3d