In the previous two articles, we introduced Flutter’s native navigator Navigator to implement the use of page jumping, routing and route interception, which can be referred to the previous article:

  1. Flutter routing and route interception jump 404 | Summer (
  2. Flutter route parameter processing | Summer (

using native routing can basically meet most of the needs, but if you want to route the page like a browser url, or control the transition animation of the page jump, then the native route needs to do a lot of modifications. on pubs, there is an excellent routing plugin fluro that solves this type of problem.

how to use fluro

the steps to use fluro are relatively simple and are divided into the following three steps:

  • build a routing instance, one application can be one instance at a time;FluroRouter
  • defines the processor () of the routing path that matches the processing methods of different routing paths.Handler
  • set up as a method in to build system routes.MaterialApponGenerateRoute FluroRouter.generator

Note that Fluro treats the path “/” as the root by default, so the root directory must be defined. In addition, if the route does not exist, you can set the definition error route handler.HandlerFluroRouter.notFoundHandler

Route processor Handler

the key implementation of fluro is , defined as follows:HandlerHandler

class Handler {  Handler({this.type = HandlerType.route, required this.handlerFunc});  final HandlerType type;  final HandlerFunc handlerFunc;}

copy the code

The constructor has two properties, the HandlerType enumeration, which is divided into two values, route and function, of which route is used for routing, which is also the default value. HandlerFunc is required, which is a method of response routing that requires returning a widget in order to jump to the corresponding page.

typedef Widget? HandlerFunc(    BuildContext? context, Map<String, List<String>> parameters);

copy the code

HandlerFuncreceive context , and carry a route parameter, which is one, multiple route parameters that correspond to a routing path. for example, if the actual route is, the format is as follows:contextMap/dynamic/:id/dynamic/1?event=a&event=bparameters

{  "id": ["1"],  "event": ["a", "b"]}

copy the code

it should be noted that the data type of the route parameter is all type, and through this, the route parameter can be passed to the subordinate page.StringHandler

usage examples

In order to manage routing uniformly, we define a class with properties that are static members so that they can be accessed directly through the class without having to create an example. Of course, considering the encapsulation, it can also be made into a singleton mode. Note that you can only initialize once, otherwise it will cause a hot reload to report an error indicating that the route has been defined. Let’s replace the route jumps in the previous two articles with fluro jumps, and the code for RouterManager is as follows:RouterManagerFluroRouter

//省略 import
class RouterManager { static String splashPath = '/'; static String loginPath = '/login'; static String homePath = '/home'; static String dynamicPath = '/dynamic'; static String dynamicDetailPath = '$dynamicPath/:id';
static FluroRouter router;
static void initRouter() { if (router == null) { router = FluroRouter(); defineRoutes(); } }
static var loginHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return LoginPage(); });
static var dynamicDetailHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return DynamicDetailPage(params['id'][0]); });
static var splashHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return Splash(); });
static var homeHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return AppHomePage(); });
static var notFoundHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) { return NotFound(); });
static void defineRoutes() { router.define(splashPath, handler: splashHandler); router.define(homePath, handler: homeHandler); router.define(loginPath, handler: loginHandler); router.define(dynamicDetailPath, handler: dynamicDetailHandler); router.notFoundHandler = notFoundHandler; }}

copy the code

in fact, you only need to call the method to complete the initialization of the route, which needs to be done in the middle of the code as follows. compared to the previous code, there is no longer a need to set parameters and parameters, but only to call the method that initializes the route in the method.RouterManager.initRoutermain.dartMaterialAppnavigationKeyinitialRoutebuild

class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    RouterManager.initRouter();    return MaterialApp(      //...      onGenerateRoute:          RouterManager.router.generator,    );  }}

copy the code

page jump

there are many forms of page jump calls, and in this example we use three, namely:

  • clear route stack jump: that is, the page after the jump is used as the root page (there is no back button), which is suitable for splashing screen pages to jump to the home page. the code is as follows:
RouterManager.router.navigateTo(context, RouterManager.homePath, clearStack: true);

copy the code

  • normal jump: jump directly without parameters, the code is as follows:
RouterManager.router.navigateTo(context, RouterManager.loginPath);

copy the code

  • jump with parameters: the routing path carries parameters, similar to ordinary jumps, except that the path parameters and query parameters are spliced together:
RouterManager.router.navigateTo(context, '${RouterManager.dynamicPath}/$id?event=a&event=b')

copy the code

run the effect

We have jumped the splash screen page to the home page, dynamically jumped to the detail page, and replaced the login page and 404 page, as shown in the following figure. Notice the difference in the overall transition, the normal transition switch is from bottom to top, but the 404 pops up from left to right (the same as the native push). This follow-up can be adjusted in the Handler or defined in the transition animation when routing jumps, and we will introduce the use of this in the next article.