Original address: medium.com/flutter-cla…

Original author: medium.com/hiashutosh

Published: April 29, 2021-5 minutes to read

Photo: Max Avans on Pexels

If you come to this page directly, make sure you browse Towards Flutter Web Part:1 before starting this page.

Now you may be wondering 🧐 why do we need to deal with routing again?

Try refreshing any screen in the project on the network, and you’ll find the entire project is rebuilt, with your application starting from the first screen, or you might observe a red screen, as I did when I refreshed the LocationScreen in the aQI_monitor project.

Let’s analyze why this is happening.

What happened under the hood was that the data only lasted until we refreshed the Flutter project. All those values we passed to a particular screen through the constructor become null because there is no previous context. Similar problems began to occur with state management packages such as providers, as our Provider objects were returned to their base state.

If you set up routing using Navigator 1.0, you should migrate to Network-enabled Navigator 2.0, or use a package like Fluro.

How does Fluro solve this problem?

Fluro offers some out-of-the-box features that are.

  • Query parameter resolution
  • Function handlers for each screen
  • It works exactly the same on mobile and the web
  • It’s easy to add transitions between screens depending on the platform type.

We can set up Fluro in our project by following these steps: —-.

1. Add it to the pubspec.yaml filefluroThe dependency of

dependencies:
  fluro: 2.03.
Copy the code

After adding dependencies, run the flutter pub get

2. Create the FluroRoutes class in lib/routes/ as 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 screenfluroRouter.define( MyHomePage.routeName, handler: homeScreenHandler, transitionType: transitionType, ); fluroRouter.define( LocationScreen.routeName, handler: locationScreenHandler, transitionType: transitionType, ); }}Copy the code

Here, we create a singleton class for FluroRoutes, we declare a transition type, which will depend on the operating system, and we declare all screen routes for the project, associated with their specific handlers.

3. Create FluroRouteHandlers in lib/routes/ as fluro_route_handlers.dart

mixin FluroRouteHandlers {
  /// Handler for MyHomePage
  var homeScreenHandler = Handler(
    handlerFunc: (
      BuildContext context,
      Map<String.List<String>> parameters,
    ) {
      returnMyHomePage(); });/// Handler for LocationScreen
  var locationScreenHandler = Handler(
    handlerFunc: (
      BuildContext context,
      Map<String.List<String>> parameters,
    ) {
      returnLocationScreen(); }); }Copy the code

Here, the handler’s role is to provide the required parameters (which we’ll see later in this article) and launch the screen.

4. In main.dart, set FluroRoutes

Set your FluroRoutes in the MaterialApp.

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) {
     returnMaterialPageRoute( builder: (context) => MyHomePage(), ); }); }}Copy the code

On the Internet, because we can change the URL to another screen, which will take you to a unknown screen does not exist in your project, so we can redirect to the project of an initial screen (such as the splash screen, the main screen), or like this in your project make a custom 404 screens, We can take advantage of this in onUnknownRoute.

5. Update the navigation process

Now that we’ve set up Fluro correctly, we’ll now update the navigation process for each screen.

I) Use Navigator for simple navigation.

The Navigator. PushNamed (context, LocationScreen routeName).

Navigator.pushNamed(context, LocationScreen.routeName);
Copy the code

Do not use the MaterialPageRoute to navigate between screens, only use the Navigator.

Ii) Use QueryParams to send data

Modify your model and parameters like this.

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;
  }
}
Copy the code

ToQueryParam is our helper function above, which converts the JSON of our model into a query format.

FromQueryParam is another helper function that converts our query parameters back into the model.

Now with “?” (Force) Symbolic link screen route name and query parameters.

Navigator.pushNamed(
  context,
  LocationScreen.routeName + '?${cityModel.toQueryParam()}',);Copy the code

In the final step, we will now modify our handler by using our helper functions. The query parameters we pass in the Navigator we will use the fromQueryParam help function to convert them into our model in the handler and pass the model or its value in our screen.

var locationScreenHandler = Handler(
  handlerFunc: (
    BuildContext context,
    Map<String.dynamic> parameters,
  ) {
    CityModel cityModel;
    if(parameters ! =null && parameters.isNotEmpty) {
      cityModel = CityModel.fromQueryParam(parameters);
    }
    returnLocationScreen( city: cityModel ! =null ? cityModel.city : null,); });Copy the code

Now, run your project on the network and try to refresh the screen in the same way as before.

You’ll notice that our screen is still on the same screen event after refreshing, and the red screen that appeared before should also disappear, because the query parameters are still in the URL, and Fluro passes these query parameters to our screen through the handler, which works fine on both Android and iOS.

So that’s the benefit of setting up this whole new routing mechanism. 😎

Important: please make sure that all the parameters and models are processed in the handler, we send them from one screen to another, you just need to convert them to query parameters, add them with the route during navigation, and then decode back into the model from query parameters.

In the next article, we’ll discuss how to make the UI responsive on both the web and mobile by keeping the same code base.


If you find this article useful, please click the clap icon 👏 and share it with your friends, as this will inspire me to write more articles.

If you have any questions about Flutter, please feel free to contact me on social media platforms.

Linktr. Ee/hiahutoshsi…


Translation via www.DeepL.com/Translator (free version)