Flutter 法法路由注解

作者: 法的空间 | 来源:发表于2019-08-20 09:15 被阅读19次

    最近改造项目,感觉Flutter路由这块需要打磨打磨,想起来之前好像听说过通过注解来生成路由映射的工具裤,嗯,很快就搜索到阿里写的annotation_route,先start一下,看了下issue,没有对页面分散到各个模块的情况进行处理,看了下issue时间,貌似没有改进的计划,放弃。

    只能自己挖井(挖坑)了,不久之前刚学会用Dart Pub Global 创建命令行应用程序
    感觉这个注解应该跟官方的json_annotation很相似,于是立刻下载下来,看源码。

    在看源码的过程中,低调大佬做了个ok_route,以及掘金一个小伙伴做了route_generator_repo,都是通过注释,来生成路由映射的解决方案,因为最后呈现方式跟自己构思的有所不同,所以还是决定继续看源码,哈哈哈,感兴趣的同学可以去看看,找到合适自己的路由注解。

    看到源码,首先映入眼帘的是

    dependencies:
      analyzer: any
    

    analyzer主要负责将dart代码转换成为ast(abstract syntax tree),具体是什么意思,我随便一搜索,又是大厂的文章
    Flutter动态化,看完感觉如果官方能支持dart代码=》AST=》dart代码的话,你们心心念念的热修复应该就能成了。

    之后我又看了下

    dependencies:
      build_runner_core: any
      build_runner: any
    

    在build_runner_core的main.dart,我看到PackageGraph如何对Package的解析。从build_runner中看到了builder执行的过程,本来想另开一篇水一下的,后面看到暴打小女孩已经写过了Flutter 注解处理及代码生成,感兴趣的小伙伴可以自己去看一下。

    现在知道了怎么解析项目结构以及引用的模块,知道怎么解析一个dart代码,写法法路由就顺利多了,下面直接上使用手册。

    使用

    增加引用

    添加引用到dev_dependencies,你需要注解的project/packages的pubspec.yaml中

    dev_dependencies:
      ff_annotation_route: any
    

    执行 flutter packages get 下载

    添加注解

    空构造

    import 'package:ff_annotation_route/ff_annotation_route.dart';
    
    @FFRoute(
      name: "fluttercandies://mainpage",
      routeName: "MainPage",
    )
    class MainPage extends StatelessWidget 
    {
          // ...
    }
    
    

    带参数构造

    import 'package:ff_annotation_route/ff_annotation_route.dart';
    @FFRoute(
        name: "fluttercandies://picswiper",
        routeName: "PicSwiper",
        argumentNames: ["index", "pics"],
        showStatusBar: false,
        pageRouteType: PageRouteType.transparent)
    class PicSwiper extends StatefulWidget {
      final int index;
      final List<PicSwiperItem> pics;
      PicSwiper({this.index, this.pics});
            // ...
      }
    

    FFRoute

    parameter description default
    name 路由的名字(e.g., "/settings"). required
    argumentNames 路由的参数的名字 -
    showStatusBar 是否显示状态栏 true
    routeName 用于埋点收集数据的页面名字 ''
    pageRouteType 路由的类型(material, cupertino, transparent) -

    生成文件

    环境

    添加dart的bin的路径到你的系统 $PATH.

    cache\dart-sdk\bin

    更多信息

    不清楚的可以看掘金

    激活

    pub global activate ff_annotation_route

    执行命令

    你可以到你的项目路径下面执行
    ff_annotation_route

    你也可以直接执行,并且带上你的项目路径
    ff_annotation_route path=

    命令参数

    使用 parameter=xxx, 使用空格隔开多个参数

    参数 描述 默认
    path 你的项目路径 当前路径
    generateRouteNames 是否在根项目中的 xxx_route.dart 生成全部路由的名字 false
    mode 0或者1, 模式1会生成 xxx_route_helper.dart 来帮助你处理 showStatusBar/routeName/pageRouteType 0
    routeSettingsNoArguments 如果为true, FFRouteSettings 将没有arguments这个参数,这个是主要是为了适配Flutter低版本 false

    Main.dart

    • 如果你设置命令带有参数 mode=1, FFNavigatorObserver/FFRouteSettings 将会生成 在 xxx_route_helper.dart
      他们帮助追踪页面和设置状态栏.

    • 如果你设置命令带有参数 mode=1,FFTransparentPageRoute 将会生成 在 xxx_route_helper.dart
      它帮助push一个透明的PageRoute.

    Widget build(BuildContext context) {
        return OKToast(
            child: MaterialApp(
          title: 'ff_annotation_route demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          navigatorObservers: [
            FFNavigatorObserver(routeChange: (name) {
              //you can track page here
              print(name);
            }, showStatusBarChange: (bool showStatusBar) {
              if (showStatusBar) {
                SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
                SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
              } else {
                SystemChrome.setEnabledSystemUIOverlays([]);
              }
            })
          ],
          builder: (c, w) {
            ScreenUtil.instance =
                ScreenUtil(width: 750, height: 1334, allowFontScaling: true)
                  ..init(c);
            var data = MediaQuery.of(c);
            return MediaQuery(
              data: data.copyWith(textScaleFactor: 1.0),
              child: w,
            );
          },
          initialRoute: "fluttercandies://mainpage",
          onGenerateRoute: (RouteSettings settings) {
            var routeResult =
                getRouteResult(name: settings.name, arguments: settings.arguments);
    
            if (routeResult.showStatusBar != null ||
                routeResult.routeName != null) {
              settings = FFRouteSettings(
                  arguments: settings.arguments,
                  name: settings.name,
                  isInitialRoute: settings.isInitialRoute,
                  routeName: routeResult.routeName,
                  showStatusBar: routeResult.showStatusBar);
            }
    
            var page = routeResult.widget ?? NoRoute();
    
            switch (routeResult.pageRouteType) {
              case PageRouteType.material:
                return MaterialPageRoute(settings: settings, builder: (c) => page);
              case PageRouteType.cupertino:
                return CupertinoPageRoute(settings: settings, builder: (c) => page);
              case PageRouteType.transparent:
                return FFTransparentPageRoute(
                    settings: settings,
                    pageBuilder: (BuildContext context, Animation<double> animation,
                            Animation<double> secondaryAnimation) =>
                        page);
              default:
                return Platform.isIOS
                    ? CupertinoPageRoute(settings: settings, builder: (c) => page)
                    : MaterialPageRoute(settings: settings, builder: (c) => page);
            }
          },
        ));
      }
    

    更多信息

    Push

    Push name

      Navigator.pushNamed(context, "fluttercandies://mainpage");
    

    Push name with arguments

    参数应该是一个 Map<String,dynamic>

       Navigator.pushNamed(context, "fluttercandies://picswiper",
                    arguments: {
                      "index": index,
                      "pics": listSourceRepository
                          .map<PicSwiperItem>(
                              (f) => PicSwiperItem(f.imageUrl, des: f.title))
                          .toList(),
                    });
    
    

    结语

    不同于其他的路由注解方案,我加入了对埋点,全屏模式以及路由类型的处理。路由注解方案很多,找到一个合适自己的就好了,欢迎提问题。

    最后放上 ff_annotation_route,欢迎加入Flutter Candies,一起生产可爱的Flutter 小糖果(QQ群:181398081)

    最最后放上Flutter Candies全家桶,真香。

    image

    相关文章

      网友评论

        本文标题:Flutter 法法路由注解

        本文链接:https://www.haomeiwen.com/subject/bmkusctx.html