https://pub.dev/packages/fluro
https://github.com/lukepighetti/fluro
Fluro作为一款优秀的Flutter企业级路由框架,Fluro的使用比官方提供的路由框架要复杂一些,但是却非常适合中大型项目。
依赖
dependencies:
fluro: ^1.7.8
# 如果无法使用上面的方式添加Fluro依赖,还可以使用git的方式添加Fluro依赖
dependencies:
fluro:
git: git://github.com/theyakka/fluro.git
导入
import 'package:fluro/fluro.dart';
使用
lib/main.dart
import "package:flutter/material.dart";
import 'package:fluro/fluro.dart';
import 'package:app1/routes/routes.dart';
import 'package:app1/routes/application.dart';
void main() {
final router = FluroRouter(); //实例化路由
Routes.configureRoutes(router); //导入路由
Application.router = router; //路由静态化,以方便全局调用
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/', //默认路由
onGenerateRoute: Application.router.generator,
);
}
}
lib/routes/application.dart 路由静态化
import 'package:fluro/fluro.dart';
class Application {
static FluroRouter router;
}
lib/routes/routes.dart 静态路由总体配置
import 'package:fluro/fluro.dart';
import 'package:app1/routes/application.dart';
import 'package:app1/routes/route_handles.dart';
class Routes {
static configureRoutes(FluroRouter router) {
// 没有发现路由页面时处理
router.notFoundHandler = Handler(
handlerFunc: (context, params) {
return Text('没有发现路由页面 $params');
},
);
router.define('/', handler: appStartHandler); // 启动页(动画结束后,自动跳至首页)
router.define('/home', handler: homeHandler); // 首页
router.define('/test', handler: testHandler);
router.define('/search', handler: searchHandler);
router.define('/webview', handler: webviewHandler);
}
/*
* 对参数进行encode,解决参数中有特殊字符; Fluro会自动解码,不需再额外处理。
* 示例 1: Routes.navigateTo(context, '/aa', params: {id: 1, title: '我是中文标题'});
* 示例 2: Routes.navigateTo(context, '/aa', arguments: {id: 1, title: '我是中文标题'});
*
* 注意:params方式、RouteSettings方式不能并存,传参时优先考虑使用params方式;
* 如果params不满足使用,再用RouteSettings方式。例如首页"/",无法使用params传参,即可使用RouteSettings方式.
*/
static Future navigateTo(
BuildContext context,
String path, { //路由名称
Map<String, dynamic> params, //search参数
bool replace = false, //是否替换当前路由栈
bool clearStack = false, //是否清空路由栈
Duration transitionDuration = const Duration(milliseconds: 250), //动画周期
RouteTransitionsBuilder transitionBuilder,
TransitionType transition = TransitionType.material, //动画方式
Map arguments, //RouteSettings 方式传参
}) async {
String query = "";
if (params != null) {
int index = 0;
for (var key in params.keys) {
if (params[key] != null) {
var value = Uri.encodeComponent(params[key].toString());
if (index == 0) {
query = "?";
} else {
query = query + "\&";
}
query += "$key=$value";
index++;
}
}
}
path = path + query;
print('跳转的页面 => $path'); //我是navigateTo传递的参数:?id=11&title=%E6%9C%B1%E6%9C%9D%E9%98%B3
return Application.router.navigateTo(
context,
path,
replace: replace, // 是否替换当前页面
clearStack: clearStack, // 是否情况页面存储栈信息
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
transition: transition,
routeSettings: arguments == null
? null
: RouteSettings(arguments: arguments),
);
}
static pop(context, [params]) {
Application.router.pop(context, params);
}
}
/*
* TransitionType.inFromLeft //左侧进入
* TransitionType.inFromRight //右侧进入
* TransitionType.inFromBottom //底部进入 默认入场动画
* TransitionType.native //无进入动画
* TransitionType.nativeModal //同上
* TransitionType.fadeIn //渐显动画
* TransitionType.custom //自定义
* TransitionType.material //感觉和上面几种一样 无特别动画效果
* TransitionType.materialFullScreenDialog //感觉和上面几种一样 无特别动画效果
* TransitionType.cupertino //右进右出
* TransitionType.cupertinoFullScreenDialog //底部进 底部出 下个页面返回值变化
*/
lib/routes/route_handles.dart 路由handler配置
最终2种传参方式(params、routeSettings)的参数,再通过 构造函数 方式 传给路由页面组件。
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:app1/pages/app_start/index.dart';
import 'package:app1/pages/home/index.dart';
import 'package:app1/pages/search/index.dart';
import 'package:app1/pages/web_view/index.dart';
import 'package:app1/pages/test/index.dart';
// app-启动页
var appStartHandler = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return AppStart();
},
);
// 首页(params 方式传参)
var homeHandler = Handler(
handlerFunc: (context, params) {
var index = params['index']?.first;
return HomePage(index: index);
},
);
// 搜索页(routeSettings 方式传参示例页面)
var searchHandler = Handler(
handlerFunc: (context, params) {
var args = context.settings.arguments;
return SearchPage(args);
},
);
// webview页面
var webviewHandler = Handler(
handlerFunc: (context, params) {
var url = params['url']?.first;
var title = params['title']?.first;
var showAppBar = params['showAppBar']?.first == 'true' ? true : false;
return WebviewPage(url: url, title: title, showAppBar: showAppBar);
},
);
// 测试demo页面
var testHandler = Handler(
handlerFunc: (context, params) {
return TestPage();
},
);
lib/pages/home/index.dart 接收参数
class HomePage extends StatefulWidget {
HomePage({
key,
this.index = '0',
}) : super(key: key);
final String index;
@override
_HomePageState createState() => _HomePageState();
}
...
lib/routes/route_push.dart 跳转
import 'package:flutter/material.dart';
import 'package:app1/routes/routes.dart';
import 'package:fluro/fluro.dart';
class RoutePush {
// 跳转到首页指定 tab RoutePush.home(context, index: 1);
static home(
context, {
int index = 0, //底部导航索引
}) {
Routes.navigateTo(
context,
'/home',
clearStack: true,
params: {
'index': index,
},
);
}
// 跳转到搜索页面(routeSettings方式传参示例页面) RoutePush.search(context, q: 'abc');
static search(
context, {
String q = '', //搜索文本
}) {
Routes.navigateTo(
context,
'/search',
arguments: {
'q': q,
},
);
}
// 跳转webview页面 RoutePush.webview(context, url: 'https://www.baidu.com', title: '百度');
static webview(
BuildContext context, {
@required String url, //网页链接
String title = '', //页面标题
bool showAppBar = true, //是否展示appBar
}) {
Routes.navigateTo(
context,
'/webview',
params: {'url': url, 'title': title, 'showAppBar': showAppBar},
);
}
}
传参
直接通过链接传参
handler配置
// webview页面
var webviewHandler = Handler(
handlerFunc: (context, params) {
var url = params['url']?.first;
var title = params['title']?.first;
var showAppBar = params['showAppBar']?.first == 'true' ? true : false;
return WebviewPage(url: url, title: title, showAppBar: showAppBar);
},
);
跳转
Application.router.navigateTo(
context,
'/webview?url=${Uri.encodeComponent(https://www.baidu.com)}&showAppBar=true',
);
接收
class ApiDemoPage extends State<ApiDemoPage> {
String title;
String id;
String isShare;
ApiDemoPage({key, this.title, this.id, this.isShare}) : super(key: key);
_getData() {
print('${title} -- ${id} -- ${isShare}'); //zhu -- 11 -- null
}
//...
}
通过 RouteSettings 传参
handler配置
var searchHandler = Handler(
handlerFunc: (context, params) {
var args = context.settings.arguments; //args {id: 11, title: zhu}
return SearchPage(args);
},
);
跳转
Application.router.navigateTo(
context,
'/search',
routeSettings: RouteSettings(
arguments: {
'id': 11,
'title': 'zhu',
},
),
);
search.dart 接收
class SearchPage extends StatelessWidget {
final args;
SearchPage(this.args);
@override
Widget build(BuildContext context) {
print('args $args'); //args {id: 11, title: zhu}
return null;
}
}
传参Map处理
传参前转为json字符串,接收时,再解码。
Application.router.pop() 返回
/// 返回上一个页面
static pop() {
// 全局 context
BuildContext myContext = navigatorKey.currentState.overlay.context;
router.pop(myContext);
}
//这里设置了一个全局 context,如果没有设置,直接把 context 传入就行了。
Application.router.pop(context);
Application.router.pop(context, 1);