发布时间:2021年4月29日 – 5分钟阅读
照片:Max Avans on Pexels
如果你是直接来到这个页面,请确保你在开始这个页面之前,先浏览一下《走向Flutter Web Part:1》。
现在你可能想知道?为什么我们需要再次处理路由?
试着在网络上刷新项目中的任何一个屏幕,你会发现整个项目重新构建,你的应用程序从第一个屏幕开始,或者你也可能观察到一个红色的屏幕,就像我在aqi_monitor项目中刷新LocationScreen时那样。
让我们分析一下为什么会发生这种情况?
在引擎盖下发生的事情是,数据只持续到我们刷新Flutter项目的时候。所有那些我们通过构造函数传递给特定屏幕的值都变成了空值,因为没有以前的上下文。类似的问题开始出现在状态管理包中,比如provider,因为我们的Provider对象被返回到他们的基本状态。
如果你使用Navigator 1.0设置了路由,你应该迁移到支持网络的Navigator 2.0,或者使用像Fluro这样的包。
Fluro如何解决这个问题?
Fluro提供了一些开箱即用的功能,这些功能是。
- 查询参数的解析
- 每个屏幕的功能处理程序
- 在手机和网页上的工作完全相同
- 很容易根据平台类型在屏幕之间添加过渡。
我们可以按照以下步骤在我们的项目中设置Fluro:—-。
1. 在pubspec.yaml文件中添加fluro的依赖项
dependencies:
fluro: 2.0.3
复制代码
添加依赖后,运行flutter pub get
2. 在lib/routes/内创建FluroRoutes类,作为fluro_routes.dart
/// setting up singleton class for FluroRoutes
class FluroRoutes with FluroRouteHandlers {
/// initializing FluroRoutes
static final FluroRoutes fluroRoutesInstance = FluroRoutes._();
factory FluroRoutes() {
return fluroRoutesInstance;
}
FluroRoutes._();
void routes(FluroRouter fluroRouter) {
TransitionType transitionType;
/// setting transition on web
if (kIsWeb) {
transitionType = TransitionType.fadeIn;
}
/// setting transition on android
else if (Platform.isAndroid) {
transitionType = TransitionType.material;
}
/// setting transition on iOS
else {
transitionType = TransitionType.cupertino;
}
/// linking handlers and routes of screen
fluroRouter.define(
MyHomePage.routeName,
handler: homeScreenHandler,
transitionType: transitionType,
);
fluroRouter.define(
LocationScreen.routeName,
handler: locationScreenHandler,
transitionType: transitionType,
);
}
}
复制代码
在这里,我们为FluroRoutes创建了一个单例类,我们声明了一个过渡类型,它将取决于操作系统,并声明了项目的所有屏幕路由,并与它们的具体处理程序相联系。
3. 在lib/routes/内创建FluroRouteHandlers作为fluro_route_handlers.dart
mixin FluroRouteHandlers {
/// Handler for MyHomePage
var homeScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, List<String>> parameters,
) {
return MyHomePage();
},
);
/// Handler for LocationScreen
var locationScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, List<String>> parameters,
) {
return LocationScreen();
},
);
}
复制代码
在这里,处理程序的作用是提供所需的参数(我们将在这篇文章的后面看到)并启动屏幕。
4. 在main.dart中设置FluroRoutes
在MaterialApp中设置你的FluroRoutes。
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final FluroRouter fluroRouter = FluroRouter();
@override
void initState() {
super.initState();
/// setting up FluroRoutes with fluroRouter
FluroRoutes().routes(fluroRouter);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "AQI Monitor",
home: MyHomePage(title: 'AQI Monitor'),
/// pass you initial screen's route in initialRoute
initialRoute: MyHomePage.routeName,
/// use fluro's generator
onGenerateRoute: fluroRouter.generator,
onUnknownRoute: (unknownRoutes) {
return MaterialPageRoute(
builder: (context) => MyHomePage(),
);
},
);
}
}
复制代码
在网络上,由于我们可以通过改变URL进入另一个屏幕,而这将把你带到一个不存在于你的项目中的未知屏幕,所以我们可以重定向到项目中的一个初始屏幕(如闪屏、主屏幕),或者像这样在你的项目中制作一个自定义的404屏幕,我们可以在onUnknownRoute中利用它。
5. 更新导航过程
现在我们已经正确地设置了Fluro,我们现在将更新每个屏幕的导航过程。
i) 使用Navigator进行简单的导航。
Navigator.pushNamed(context, LocationScreen.routeName)。
Navigator.pushNamed(context, LocationScreen.routeName);
复制代码
不要使用MaterialPageRoute在屏幕间导航,只使用Navigator。
ii) 使用QueryParams来发送数据
像这样修改你的模型和参数。
class CityModel {
String city;
CityModel({
this.city,
});
CityModel.fromJson(Map<String, dynamic> json) {
city = json['city'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['city'] = city;
return data;
}
String toQueryParam() {
return Uri(queryParameters: toJson()).query;
}
CityModel.fromQueryParam(Map<String, dynamic> jsonMap) {
city = jsonMap['city']?.first;
}
}
复制代码
toQueryParam是我们上面的辅助函数,它将我们模型的JSON转换为查询格式。
fromQueryParam是另一个辅助函数,将我们的查询参数转换回模型。
现在用”?”(强制)符号连接屏幕路线名称和查询参数。
Navigator.pushNamed(
context,
LocationScreen.routeName + '?${cityModel.toQueryParam()}',
);
复制代码
在最后一步,我们现在将通过使用我们的辅助函数来修改我们的处理程序。我们在Navigator中传递的查询参数,我们将在处理程序中使用fromQueryParam帮助函数将它们转换为我们的模型,并在我们的屏幕中传递该模型或其值。
var locationScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, dynamic> parameters,
) {
CityModel cityModel;
if (parameters != null && parameters.isNotEmpty) {
cityModel = CityModel.fromQueryParam(parameters);
}
return LocationScreen(
city: cityModel != null ? cityModel.city : null,
);
},
);
复制代码
现在,在网络上运行你的项目,也尝试用与之前相同的方式刷新屏幕。
你会观察到,我们的屏幕在刷新后仍然在同一个屏幕事件上,而且之前出现的红屏也应该消失了,因为查询参数仍然在URL中,Fluro通过处理程序将这些查询参数传递给我们的屏幕,这个设置在Android和iOS上也都能顺利运行。
所以这就是设置这个新的整个路由机制的好处。?
重要提示:请确保在处理程序中处理所有的参数和模型,我们从一个屏幕发送到另一个屏幕,你只需要将它们转换为查询参数,在导航时与路由一起添加,然后从查询参数解码回到模型中。
在下一篇文章中,我们将讨论如何通过保持相同的代码库使UI在网络和移动端上都能响应。
如果你觉得这篇文章有用,请点击拍手图标?并与你的朋友分享,因为这将激励我写更多的文章。
如有任何关于Flutter的疑问,请随时在社交媒体平台上与我联系。
通过www.DeepL.com/Translator(免费版)翻译