Flutter basic routing management, use of Fluro library and secondary encapsulation

In native development, Android and IOS have their own control page (Activity, ViewControl) function to jump, and in flutter, routing management has become more unified, flexible and efficient.

Routing Management Requirements

In Flutter, everything is a component, a page is also a component, and routing is a jump and value transfer between components. There are four common requirements:

  1. Jump to next page
  2. go back to the last page
  3. forward value
  4. pass-by-value

We mainly study these four modes of operation, which are necessary requirements in each project.

MaterialApp built-in routing management

The routing management built into MaterialApp has two modes of operation:

  1. Routes are not declared, use instantiated components to jump directly
  2. Declare a route and use the name of the route to jump

The two methods have their own advantages and disadvantages, which can be chosen as appropriate in the project. The first method is more flexible and simple to eliminate violence, but it cannot be managed in a unified manner, which is relatively loose. Values ​​can be cumbersome.

As mentioned earlier, pages in flutter are also components, so we first use the Scaffold scaffolding to create two separate pages: HomePage and NextPage. Use these two pages to implement all subsequent requirements:

do not declare routes

1. Jump to the next page

Without declaring the component, use the api to jump to the component page in the callback directly:

// HomePage page
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (ctx) => NextPage()));
          },
          child: Text("Jump to the second page"),
        ),
      ),
    );
  }
}

// NextPage page
class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Next Page"),
      ),
      body: Container(
        child: Text("Next Page"),
      ),
    );
  }
}

Using the api directly, you can make quick page jumps, among which the key jump code

...
Navigator.push(context, MaterialPageRoute(builder: (ctx) => NextPage()));
...

Because it is the default jump method, there will be different animation effects on Android and Apple: Android fades from bottom to top, while ios slides in from right to left.

2. Jump pass value

If you pass a value, it should be very clear at a glance. Set the data attribute on the corresponding page. When instantiating, you can set it directly. The key code:

// HomePage
...
Navigator.push(context, MaterialPageRoute(builder: (ctx) {
  return NextPage(
    data: "Home Page Data",
  );
}));
...
// NextPage
class NextPage extends StatelessWidget {
  String data;
  NextPage({this.data});
...
}

3. Return to previous page

...
Navigator.pop(context);
...

4. Reverse pass value

The second parameter of the Navigator.pop method mentioned above can pass any type of data, and this parameter is the content of the reverse value.

The Navigator.push method on the home page returns a Future, which is the second parameter of the Navigator.pop function of the pop-up page. We can use async and await to quickly get the content:

//
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            var returnData = await Navigator.push(context, MaterialPageRoute(builder: (ctx) => NextPage()));
            print("Next Page return to Home Page:  ${returnData}");
          },
          child: Text("Jump to the second page"),
        ),
      ),
    );
  }
}

//
class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Next Page"),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                Navigator.pop(context, {"data": "Reverse pass value content"});
              },
              child: Text("go back to the last page"),
            )
          ],
        ),
      ),
    );
  }
}

After jumping to NextPage, click to return to the previous page, and you can see the console output:

I/flutter (11371): Next Page return to Home Page:  {data: Reverse pass value content}

This is the return value operation performed by the Navigator.pop function. If the return icon in the page AppBar is clicked, the return value is null

declare route

1. Jump to the next page

MaterialApp has a built-in routing management function, declare the route name and corresponding component in the routes parameter in the MaterialApp class:

class FeDemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: {
        "/": (ctx) => HomePage(),
        "NextPage": (ctx) => NextPage(),
      },
    );
  }
}

After declaring the name and component, we can directly use the name to perform routing operations:

...
// 'NextPage' has been declared as a NextPage() component
Navigator.pushNamed(context, "NextPage");
...

2. Back to the previous page

The way to return to the previous page is the same in both management methods, using Navigator.pop

...
Navigator.pop(context, {"a": "pass-by-value"});
...

3. Forward value

The forward pass value is different, because in the way of not declaring the route, we can directly contact the object of the corresponding page, but in the way of declaring the route, the corresponding object has been created at the time of declaration, and in the jump can't be obtained directly, so the way of passing the value and getting it is different.

When passing values, use the arguments parameter in Navigator.pushNamed:

...HomePage
// 'NextPage' has been declared as a NextPage() component
Navigator.pushNamed(context, "NextPage", arguments: "pass by value");
...

When fetching, use the following code:

... NextPage
// get value
var data = ModalRoute.of(context).settings.arguments;
...

4. Reverse pass value

Consistent with the undeclared method, Navigator.pushNamed also returns a Future.

Fluro routing library

With the emergence of flutter, a number of excellent libraries were born, and fluro is one of them.

It is more flexible, has lower coupling, supports various page switching animations, and can achieve easy routing management and permission interception with simple secondary encapsulation.

basic use

fluro needs to declare routes in advance, and all routing operations need to apply to the global Router object.

import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';

final router = Router();

void main() {
  // declare route
  router.define(
    "/NextPage",
    handler: Handler(
      handlerFunc: (ctx, params) {
        return NextPage();
      },
    ),
  );
  runApp(FeDemoApp());
}

class FeDemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

//
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () async {
            var returnData = await router.navigateTo(
              context,
              "/NextPage",
              transition: TransitionType.nativeModal,
            );
            print("return value: ${returnData}");
          },
          child: Text("Jump to the second page"),
        ),
      ),
    );
  }
}

//
class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Next Page"),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text("go back to the last page"),
            )
          ],
        ),
      ),
    );
  }
}

We can modify the jump animation TransitionType.cupertino to display the slide-in and slide-out effect of ios on the Android side.

fluro secondary encapsulation class

The following is a simple encapsulation of fluro, which unifies the global routing objects. The routing name uses static parameters, the jump method is also styled, and the page interception is also easy to expand:

import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';

import 'main.dart' as Main;

class App {
  static final router = Router();

  static String HomePage = "/HomePage";
  static String NextPage = "/NextPage";

  // Initialize route
  static void initRouter() {
    var routers = {
      "${HomePage}": Handler(
        handlerFunc: (ctx, params) => Main.HomePage(),
      ),
      "${NextPage}": Handler(
        handlerFunc: (ctx, params) => Main.NextPage(),
      ),
    };

    routers.forEach((key, value) {
      router.define(key, handler: value);
    });
  }

  static Future<dynamic> PageTo(BuildContext context, String path) {
    return router.navigateTo(
      context,
      path,
      transition: TransitionType.nativeModal,
    );
  }

  static Future<dynamic> AuthTo(BuildContext context, String path) {
    // TODO: Verify permissions, and then decide where to jump
    var auth = true;
    if (auth) {
      return router.navigateTo(
        context,
        path,
        transition: TransitionType.nativeModal,
      );
    } else {
    // Verification failed, jump to the home page
      return router.navigateTo(
        context,
        HomePage,
        transition: TransitionType.nativeModal,
      );
    }
  }
}

Simple packaging, you can leave a message to express different ideas!

Tags: Front-end Flutter dart

Posted by dotbands on Tue, 24 May 2022 15:17:08 +0300