Flutter realizes the transmission and analysis of routing parameters

Last Implementation of fluent page routing and 404 route interception This paper introduces the use of routing to realize page Jump, so as to simplify the coupling between pages and realize route interception. In actual development, we often need to carry routing parameters when the page jumps. A typical example is when we go from the list to the details page, we need to carry the details id so that the details page can obtain the corresponding data. At the same time, sometimes it is necessary to carry parameters back to the upper level when returning, so that the superior page can be updated according to the returned results. This article will introduce the implementation of these two situations.

push and pop methods of Navigator

The push and pop methods of the Navigator navigator can carry parameters to pass between pages, as can other deformation methods. The prototype of pushNamed method is as follows:

Future<T?> pushNamed<T extends Object?>(
  String routeName, {
  Object? arguments,
}) {
  return push<T>(_routeNamed<T>(routeName, arguments: arguments)!);
}

In addition to the named route of routeName, there is an optional parameter arguments, which is used to pass parameters on the route page. The pop method is the same:

void pop<T extends Object?>([ T? result ]) {
  //...
}

You can carry a result back to the superior page.

code implementation

We use a list to jump to the details page to demonstrate route parameter acquisition (see the list construction article) Introduction and practice of Flutter (V): a list with pictures and texts ). When clicking a list row, the id of the list data item will be carried to jump to the details page. When returning from the details page, the id will be returned. The Widget of the list item adds an id attribute, which is initialized when building the list.

class DynamicItem extends StatelessWidget {
  final int id;
  final String title;
  final String imageUrl;
  final int viewCount;
  static const double ITEM_HEIGHT = 100;
  static const double TITLE_HEIGHT = 80;
  static const double MARGIN_SIZE = 10;
  const DynamicItem(this.id, this.title, this.imageUrl, this.viewCount,
      {Key key})
      : super(key: key);
  //...
}

The container of the list is wrapped with GestureDetector to respond to click events. The onTap method is defined as an async method to use await to obtain the parameters when the navigation returns, and a SnackBar to display the returned id. Here pushNamed carries a Map object and passes the id of the list to the details page.

@override
Widget build(BuildContext context) {
  return GestureDetector(
    child: Container(
      margin: EdgeInsets.all(MARGIN_SIZE),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _imageWrapper(this.imageUrl),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _titleWrapper(context, this.title),
                _viewCountWrapper(this.viewCount.toString()),
              ],
            ),
          )
        ],
      ),
    ),
    onTap: () async {
      Map<String, dynamic> routeParams = {'id': id};
      var arguments = await Navigator.of(context)
          .pushNamed(RouterTable.dynamicDetail, arguments: routeParams);
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text("From dynamic ${(arguments as Map<String, dynamic>)['id']}return"),
      ));
    },
  );
}

Here, an arguments variable is also used to receive the parameters returned by the navigation. If the navigation has returned parameters, a Future object will be returned, which can be received by using await. Then it is converted to the actual type using as.
On the details page, fluent provides a ModalRoute class to obtain routing configuration parameters from the current context. The code is as follows:

class DynamicDetail extends StatelessWidget {
  const DynamicDetail({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Map<String, dynamic> routeParams =
        ModalRoute.of(context).settings?.arguments;

    return WillPopScope(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Dynamic Details'),
          brightness: Brightness.dark,
        ),
        body: Center(
          child: Text("product id: ${routeParams['id']}"),
        ),
      ),
      onWillPop: () async {
        Navigator.of(context).pop({'id': routeParams['id']});
        return true;
      },
    );
  }
}

In fact, this ModalRoute.of(context).settings is the settings parameter of ongeneraterote in our previous route interception. Therefore, assuming that we need to add additional routing parameters (such as global parameters), we can reassemble the routing parameters in the ongeneraterote method.
There is a point to note here. Because parameters are carried when returning, we need to intercept the return response event. At this time, the whole component can be wrapped with WillPopScope. This method has two parameters:

  • child: sub component, that is, the original page component;
  • onWillPop: intercept processing before returning, and return a future < bool > object. If it is false, it will not be returned. If true, the previous level will be returned. Here, we call the pop method with parameters to return the parameters. In fact, some other processing is often done here, such as asking whether to confirm to leave when the form is not saved, and the activity page of the majority of e-commerce asks you whether to "leave with pain" or "look again".

Final effect

The final running effect is shown in the figure below. The id parameter is obtained on the details page, and the corresponding id is also received when returning.

Route parameter interception

Routing parameters can be intercepted by ongeneraterote for additional processing. The example code is as follows. It should be noted that this is only an example because of settings. arguments can be of any type, which may cause the conversion to fail. In actual business, it is better to agree on the transmission type of routing parameters to avoid exceptions caused by inconsistent parameter forms.

static Route onGenerateRoute<T extends Object>(RouteSettings settings) {
  var arguments = settings.arguments as Map<String, dynamic>;
  if (arguments != null) {
    arguments['event'] = 'Added parameters for route interception';
  }
  RouteSettings newSettings =
      settings.copyWith(name: settings.name, arguments: arguments);

  return CupertinoPageRoute<T>(
    settings: newSettings,
    builder: (context) {
      String name = settings.name;
      if (routeTables[name] == null) {
        name = notFoundPath;
      }

      Widget widget = routeTables[name](context);

      return widget;
    },
  );
}

summary

This chapter introduces the transmission examples of routing parameters and parameter modification after route interception. In the actual process, routing parameters are generally transmitted to the lower level. It is necessary to try to avoid returning parameters to realize data transmission, resulting in serious coupling between upper and lower pages, which is best realized through state management. At present, this route management will also have some inconveniences, such as the inability to pass variable parameters in the path name like the url of the web page, and the inability to control the transition animation of page Jump. Fluro routing management is very popular in pub. The next article introduces how to use fluro to realize page routing.

Tags: iOS Android Flutter

Posted on Tue, 30 Nov 2021 17:22:32 -0500 by jminscoe