In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article introduces how to efficiently solve the Flutter routing management code so long, the content is very detailed, interested friends can refer to, I hope it can be helpful to you.
01 background
In the process of Flutter service development, the Flutter side will gradually enrich its own routing management. A lightweight routing management is essentially a mapping between the page identity (or page path) and the page instance. In this paper, the engineer will provide a lightweight routing management scheme based on dart annotations.
Whether it is a hybrid project of native and Flutter or a project developed by pure Flutter, when we implement a lightweight route, we generally have the following methods:
1. Poor implementation, logical stack of if-else:
The poor implementation of mapping is to map the url to the corresponding widget instance through the logical judgment of if-else.
Class Router {Widget route (String url, Map params) {if (url = = 'myapp://apage') {return PageA (url);} else if (url = =' myapp://bpage') {return PageB (url, params);}
The disadvantages of doing so are obvious:
1) the maintenance of each mapping affects the stability of the global mapping configuration, and all the logical branches are needed for each maintenance of mapping management.
2) unable to achieve the unified abstraction of the page, the page constructor and construction logic are defined by the developer.
3) the mapping configuration can not be linked with the page to centralize the maintenance of the page-level configuration, resulting in the lack of maintenance responsibility.
two。 General implementation, manually maintained mapping table:
It is slightly better to represent the mapping relationship through a configuration information and a factory method.
Class Router {Map mypages = {'myapp://apage':' pagea', 'myapp://bpage':' pageb'} Widget route (String url, Map params) {String pageId = mypages [url]; return getPageFromPageId (pageId);} Widget getPageFromPageId (String pageId) {switch (pageId) {case 'pagea': return PageA () Case 'pageb': return PageB ();} return null;}
This approach is still troublesome on the fluter side, first, problem 3 still exists, and secondly, because Flutter currently does not support reflection, there must be a factory-like way to create page instances.
In order to solve the above problems, we need a set of solutions that can be used at the page level and automatically maintain mappings. Annotations are a direction worth trying. Our route annotation scheme annotation_route arises at the historic moment, and the running system of the entire annotation scheme is shown in the figure:
Let's start with the dart annotations to understand how the system works.
02 dart comments
Annotations are actually a section of configuration at the code level, which can be used at compile time or run time. Because Flutter does not support runtime reflection, we need to get the relevant information of annotations at compile time, and use this information to generate an automatic maintenance mapping table. What we need to do is to analyze the syntax structure of the dart file, find the comment blocks and relevant contents of the comments in the file, collect the annotation contents, and finally generate the desired mapping table. The idea of this solution is shown in the figure:
In the survey, it is found that some of the built-in libraries of dart have accelerated the landing of this scheme.
03 Source_gen
Dart provides three libraries: build, analyser and source_gen, among which source_gen uses build library and analyser library to give a better encapsulation of annotation interception. From the point of view of annotation function, these three libraries give the following functions respectively:
Build library: processing of a complete set of resource files
Analyser library: generate a complete syntax structure for dart files
Source_ gen library: provides interception of annotation elements
Here is a brief introduction to source_gen and its upstream and downstream. Let's first take a look at the class diagrams related to its annotations:
The source of source_gen is the Builder base class provided by the build library, which allows users to customize the resource files being processed. It is responsible for providing resource file information and providing methods for generating new resource files. Source_gen derives its own builder from the Builder class provided by the build library, and customizes a set of abstractions of generator Generator. The derived builder accepts a collection of Generator classes, then collects the output of Generator, and finally generates a file. Different derived builder deal with generator differently. In this way, source_gen hands over the construction process of a file to multiple Generator defined by itself, and provides a relatively friendly encapsulation compared to the build library.
Based on the abstract generator Generator, source_gen provides an annotation-related generator GeneratorForAnnotation. An annotation generator instance accepts a specified annotation type. Since analyser provides the abstract element Element of the syntax node and its metadata field, that is, the syntactic abstract element ElementAnnotation of the annotation, the annotation generator can check whether the metadata type of each element matches the declared annotation type. In order to filter out the information of the annotated element and the context of the element, and then package the information to the user, we can use this information to complete the routing annotation.
04 annotation_route
After learning about source_gen, we began to work on our own annotation parsing scheme. When annotation_route first got involved, we encountered several problems:
Only one file needs to be generated: since an input file corresponds to a generated file suffix, we need to avoid redundant file generation
We need to know when to generate the file: we need to generate the mapping table after all the alternate files have been scanned and collected.
Source_gen supports only one annotation for a class, but there are multiple url maps to one page
After thinking about it, we have the following output
First, annotations are divided into two categories, one for the annotation page @ ARoute, and the other for annotating the user's own router@ARouteRoot. RouteBuilder owns RouteGenerator instance and RouteGenerator instance, which is responsible for @ ARoute annotation; routeWriteBuilder owns RouteWriterGenerator instance, which is responsible for @ ARouteRoot annotation. Through the configuration file build.yaml supported by the build library, control the construction order of the two types of builder, and execute routeWriteBuilder after the completion of the routeBuilder execution, so that we can accurately start to generate our own configuration files after all the pages are annotated and scanned.
In the annotation resolution project, for the @ ARoute annotated page, the configuration information is handed over to the Collector with static storage space through RouteGenerator, and the output is set to null, that is, the corresponding file will not be generated. After all the pages annotated by @ ARoute have been scanned, RouteWriteGenerator invokes Writer, which extracts information from Collector and generates the final configuration file. For users, we provide a layer of friendly encapsulation, and after using annotation_route to configure to the project, our routing code has changed as follows:
Before use:
Import 'testa.dart'import' testb.dart'import 'testc.dart'import' testd.dart'import 'teste.dart'import' testf.dart' class Router {Widget pageFromUrlAndQuery (String urlString, Map query) {if (urlString = = 'myapp://testa') {return TestA (urlString, query);} else if (urlString = =' myapp://testb') {String absoluteUrl = Util.join (urlString, query) Return TestB (url: absoluteUrl);} else if (urlString = = 'myapp://testc') {String absoluteUrl = Util.join (urlString, query); return TestC (config: absoluteUrl);} else if (urlString = =' myapp://testd') {return TestD (PageDOption (urlString, query)) } else if (urlString = = 'myapp://teste') {return TestE (PageEOption (urlString, query));} else if (urlString = =' myapp://testf') {return TestF (PageFOption (urlString, query));} return DefaultWidget;}}
After use:
Import 'package:annotation_route/route.dart'; class MyPageOption {String url; Map query; MyPageOption (this.url, this.query);} class Router {ARouteInternal internal = ARouteInternalImpl (); Widget pageFromUrlAndQuery (String urlString, Map query) {ARouteResult routeResult = internal.findPage (ARouteOption (url: urlString, params: query), MyPageOption (urlString, query)); if (routeResult.state = = ARouteResultState.FOUND) {return routeResult.widget } return DefaultWidget;}} about how to efficiently solve the long Flutter routing management code is shared here. I hope the above content can be helpful to everyone and learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.