Flutter路由框架Fluro使用说明
Posted 唯鹿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter路由框架Fluro使用说明相关的知识,希望对你有一定的参考价值。
1.Navigator使用简介
使用Flutter 的Navigator
导航器可以实现页面的跳转,Navigator
的使用方法简单介绍一下:
- 页面跳转:
Navigator.push<void>(
context,
MaterialPageRoute(
builder: (BuildContext context) => const MyHomePage(),
),
);
- 页面跳转的同时关闭当前页面(页面替换):
Navigator.pushReplacement<void, void>(
context,
MaterialPageRoute(
builder: (BuildContext context) => const MyHomePage(),
),
);
- 页面跳转的同时关闭到之前的某一个页面:
Navigator.pushAndRemoveUntil<void>(
context,
MaterialPageRoute(
builder: (BuildContext context) => const MyHomePage(),
),
(route) => false // ModalRoute.withName('/')
);
也可以直接使用路由名称进行上面操作,例如跳转:Navigator.pushNamed(context, '/home');
路由名称需要提前在MaterialApp
中定义好。
MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
routes:
"/page1": (context) => PageA(),
"/page2": (context) => PageB(),
,
);
接收参数:var args = ModalRoute.of(context).settings.arguments;
- 页面返回
Navigator.pop(context);
- 接收页面的返回值:
Navigator.push<void>(
context,
MaterialPageRoute(
builder: (BuildContext context) => const MyHomePage(),
),
).then((dynamic result)
// 页面返回result
);
必须同时配合Navigator.pop<dynamic>(context, result);
还有路由删除removeRoute
,路由替换replace
等。
2.fluro
直接使用Navigator
的主要问题是不易维护。如果某个页面的传参发生了变化,那么所有跳转处都需要做修改。
所以我们可以使用现有封装好的路由框架来替我们解决这些问题。比如fluro。
1.配置
添加依赖至pubspec.yaml
:
dependencies:
fluro: ^2.0.3
定义唯一一个FluroRouter
对象:
static final FluroRouter router = FluroRouter();
剩下的就是添加路由处理器Handler
,下面代码举例添加了两个页面:
class Routes
static String home = '/home';
static String webViewPage = '/webView';
static final List<IRouterProvider> _listRouter = [];
static final FluroRouter router = FluroRouter();
static void initRoutes()
/// 指定路由跳转错误返回页
router.notFoundHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params)
debugPrint('未找到目标页');
return const NotFoundPage();
);
router.define(home, handler: Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) => const Home()));
// Routes.router.navigateTo(context, '$Routes.webViewPage?title=标题&url=地址');
router.define(webViewPage, handler: Handler(handlerFunc: (_, params)
/// 接收参数
final String title = params['title']?.first ?? '';
final String url = params['url']?.first ?? '';
return WebViewPage(title: title, url: url);
));
配置fluro:
MaterialApp(
onGenerateRoute: Routes.router.generator,
);
初始化:
class MyApp extends StatelessWidget
MyApp()
Routes.initRoutes();
...
2.使用方法
核心就一个方法navigateTo
,源码如下:
Future navigateTo(BuildContext context, String path,
bool replace = false,
bool clearStack = false,
bool maintainState = true,
bool rootNavigator = false,
TransitionType? transition,
Duration? transitionDuration,
RouteTransitionsBuilder? transitionBuilder,
RouteSettings? routeSettings)
RouteMatch routeMatch = matchRoute(context, path,
transitionType: transition,
transitionsBuilder: transitionBuilder,
transitionDuration: transitionDuration,
maintainState: maintainState,
routeSettings: routeSettings);
Route<dynamic>? route = routeMatch.route;
Completer completer = Completer();
Future future = completer.future;
if (routeMatch.matchType == RouteMatchType.nonVisual)
completer.complete("Non visual route type.");
else
///找不到时走`notFoundHandler`
if (route == null && notFoundHandler != null)
route = _notFoundRoute(context, path, maintainState: maintainState);
if (route != null)
final navigator = Navigator.of(context, rootNavigator: rootNavigator);
if (clearStack)
future = navigator.pushAndRemoveUntil(route, (check) => false);
else
future = replace
? navigator.pushReplacement(route)
: navigator.push(route);
completer.complete();
else
final error = "No registered route was found to handle '$path'.";
print(error);
completer.completeError(RouteNotFoundException(error, path));
return future;
path
:路由名称。replace
:等同于pushReplacement
。clearStack
:等同于pushAndRemoveUntil
。transition
:页面跳转动画,默认native,平台默认动画。transitionDuration
:动画时长。transitionBuilder
:自定义动画。routeSettings
:用于传递数据。可使用context.settings.arguments
获取。
具体的使用见项目routers目录。
3.路由拦截
路由拦截可以实现权限控制。比如用户没有登录,当进入某些需要登录后才能显示的页面时,可以拦截跳转进行判断,引导用户进入登录页。
MaterialApp有 onGenerateRoute
方法可以在跳转时进行路由拦截。但是使用的fluro将这一属性占用了,所以我们可以继承 FluroRouter
类,重写navigateTo
方法实现。
class MyFluroRouter extends FluroRouter
List<String> _loginList;
set loginList(value) => _loginList = value;
Future navigateTo(
BuildContext context,
String path,
bool replace = false,
bool clearStack = false,
bool maintainState = true,
bool rootNavigator = false,
TransitionType transition,
Duration transitionDuration,
transitionBuilder,
RouteSettings routeSettings,
)
String pathToNavigate = path;
AppRouteMatch routeMatched = this.match(path);
String routePathMatched = routeMatched?.route?.route;
if (routePathMatched != null)
//如果页面需要登录,修改路由路径到登录页面
if (_loginList != null && !_loginList.contains(routePathMatched))
pathToNavigate = ’/login‘;
return super.navigateTo(context, pathToNavigate,
replace: replace,
clearStack: clearStack,
maintainState: maintainState,
rootNavigator: rootNavigator,
transition: transition,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
routeSettings: routeSettings);
3.封装
fluro工具类:
class NavigatorUtils
static void push(BuildContext context, String path,
bool replace = false, bool clearStack = false, Object? arguments)
unfocus();
Routes.router.navigateTo(context, path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.native,
routeSettings: RouteSettings(
arguments: arguments,
),
);
static void pushResult(BuildContext context, String path, Function(Object) function,
bool replace = false, bool clearStack = false, Object? arguments)
unfocus();
Routes.router.navigateTo(context, path,
replace: replace,
clearStack: clearStack,
transition: TransitionType.native,
routeSettings: RouteSettings(
arguments: arguments,
),
).then((Object? result)
// 页面返回result为null
if (result == null)
return;
function(result);
).catchError((dynamic error)
debugPrint('$error');
);
/// 返回
static void goBack(BuildContext context)
unfocus();
Navigator.pop(context);
/// 带参数返回
static void goBackWithParams(BuildContext context, Object result)
unfocus();
Navigator.pop<Object>(context, result);
static void unfocus()
FocusManager.instance.primaryFocus?.unfocus();
模块管理:
import 'package:fluro/fluro.dart';
abstract class IRouterProvider
void initRouter(FluroRouter router);
实现接口:
class LoginRouter implements IRouterProvider
static String loginPage = '/login';
static String registerPage = '/login/register';
void initRouter(FluroRouter router)
router.define(loginPage, handler: Handler(handlerFunc: (_, __) => const LoginPage()));
router.define(registerPage, handler: Handler(handlerFunc: (_, __) => const RegisterPage()));
各模块初始化,放在Routes的initRoutes中:
/// 各自路由由各自模块管理,统一在此添加初始化
_listRouter.add(LoginRouter());
...
/// 初始化路由
void initRouter(IRouterProvider routerProvider)
routerProvider.initRouter(router);
_listRouter.forEach(initRouter);
目前Flutter团队有维护一款路由框架go_router
(支持Navigator 2.0),但目前有部分功能缺失,比如不支持接收页面的返回值,没有pushAndRemoveUntil
方法。
期待后面功能的完善。但就目前来说,对于android 和ios平台开发来说fluro的功能足够使用了。
以上是关于Flutter路由框架Fluro使用说明的主要内容,如果未能解决你的问题,请参考以下文章