[Flutter翻译]通往Flutter Web的旅程第二部分:用Fluro进行路由选择

原文地址:medium.com/flutter-cla…

原文作者:medium.com/@hiashutosh

发布时间:2021年4月29日 – 5分钟阅读

image.png

照片:Max Avans on Pexels

如果你是直接来到这个页面,请确保你在开始这个页面之前,先浏览一下《走向Flutter Web Part:1》

现在你可能想知道?为什么我们需要再次处理路由?

试着在网络上刷新项目中的任何一个屏幕,你会发现整个项目重新构建,你的应用程序从第一个屏幕开始,或者你也可能观察到一个红色的屏幕,就像我在aqi_monitor项目中刷新LocationScreen时那样。

image.png

让我们分析一下为什么会发生这种情况?

在引擎盖下发生的事情是,数据只持续到我们刷新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上也都能顺利运行。

所以这就是设置这个新的整个路由机制的好处。?

image.png

image.png

重要提示:请确保在处理程序中处理所有的参数和模型,我们从一个屏幕发送到另一个屏幕,你只需要将它们转换为查询参数,在导航时与路由一起添加,然后从查询参数解码回到模型中。

在下一篇文章中,我们将讨论如何通过保持相同的代码库使UI在网络和移动端上都能响应。


如果你觉得这篇文章有用,请点击拍手图标?并与你的朋友分享,因为这将激励我写更多的文章。

如有任何关于Flutter的疑问,请随时在社交媒体平台上与我联系。

linktr.ee/hiahutoshsi…


通过www.DeepL.com/Translator(免费版)翻译

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享