Flutter利用注解生成可自定义的路由的实现

前端之家收集整理的这篇文章主要介绍了Flutter利用注解生成可自定义的路由的实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

route_generator是什么

这是一个简单的 Flutter 路由生成库,只需要少量的代码,然后利用注解配合源代码生成自动生成路由表,省去手工管理路由代码的烦恼。

特性

  • 自定义路由名称
  • 自定义路由动画
  • 自定义路由参数
  • 自定义路由逻辑
  • @H_502_19@

    依赖

    dependencies:
     # Your other regular dependencies here
     route_annotation: ^0.1.0
    
    dev_dependencies:
     # Your other dev_dependencies here
     build_runner: ^1.5.0
     route_generator: ^0.1.2
    

    生成代码

    单次构建

    在项目根目录中运行flutter pub run build_runner build,可以在需要时为项目生成路由代码。这会触发一次性构建,该构建遍历源文件,选择相关文件,并为它们生成必要的路由代码。虽然这很方便,但如果您不必每次在模型类中进行更改时都必须手动构建,那么你可以选择持续构建。

    持续构建

    在项目根目录中运行flutter pub run build_runner watch来启动watcher,它可以使我们的源代码生成过程更加方便。它会监视项目文件中的更改,并在需要时自动构建必要的文件

    route_annotation

    annotation description
    Router 此注解用来标志某个为 Flutter App 的类,并以此生成相应的路由代码
    RoutePage 此注解用来注解一个路由页面
    RouteParameter 一个用来标志页面参数的注解,只为可选参数设计。用于 RoutePage 。
    RouteField 此注解用来标志一个完全自定义的路由,被注解的对象必须作为路由页面类静态字段
    PageRouteBuilderFuntcion 这个注解用来标识一个路由页面的 RouteFactory 静态方法
    RoutePageBuilderFunction 这个注解用来标识一个路由页面的 RoutePageBuilder静态方法
    RouteTransitionBuilderFunction 这个注解用来标识一个路由页面的 TransitionBuilder 静态方法
    RouteTransitionDurationField 这个注解用来标识一个自定义路由页面的过渡时长

    代码示例

    定义路由 App

    @Router()
    class DemoApp extends StatefulWidget {
     @override
     _DemoAppState createState() => _DemoAppState();
    }
    
    class _DemoAppState extends State<DemoApp> {
     @override
     Widget build(BuildContext context) {
      return MaterialApp(
       initialRoute: "/",onGenerateRoute: onGenerateRoute,);
     }
    }
    

    定义路由页面

    // isInitialRoute为true表示它将作为initial page
    @RoutePage(isInitialRoute: true)
    class HomePage extends StatelessWidget {
     @override
     Widget build(BuildContext context) {
      return Scaffold();
     }
    }
    

    定义路由页面参数

    对于单个参数

    @RoutePage(params: [RouteParameter("title")])
    class OneArgumentPage extends StatelessWidget {
     final String title;
    
     const OneArgumentPage({Key key,this.title}) : super(key: key);
    
     @override
     Widget build(BuildContext context) {
      return Container();
     }
    }
    

    导航

    Navigator.of(context).pushNamed(
     ROUTE_ONE_ARGUMENT_PAGE,arguments: "title is empty",);
    

    注意事项:

    对于单个参数的路由,利用Navigator进行导航的时候arguments即为原始参数。

    对于多个参数

    @RoutePage(params: [RouteParameter("title"),RouteParameter("subTitle")])
    class TwoArgumentPage extends StatelessWidget {
     final String title;
     final String subTitle;
    
     TwoArgumentPage({this.title,Key key,this.subTitle}) : super(key: key);
    
     @override
     Widget build(BuildContext context) {
      return Scaffold();
     }
    }
    

    导航

    Navigator.of(context).pushNamed(
     ROUTE_TWO_ARGUMENT_PAGE,arguments: {
      "title": _titleController.text.isNotEmpty
        ? _titleController.text
        : "title is empty","subTitle": _subTitleController.text.isNotEmpty
        ? _subTitleController.text
        : "sub title is empty",},);
    

    注意事项:

    对于多个参数的路由,利用Navigator进行导航的时候arguments必须为Map<string,dynamic>。

    如果你不需要自定义路由,以下部分,你可以什么都不用添加,就让route_generator为你自动生成相关代码吧!

    自定义路由(优先级:3)

    这种方法自定义路由的优先级最高,如果同时存在多种自定义路由选择,该种方案最先被选择。

    @RoutePage()
    class CustomRoutePage extends StatelessWidget {
     @RouteField()
     static Map<String,RouteFactory> route = <String,RouteFactory>{
      'custom_route': (RouteSettings settings) =>
        MaterialPageRoute(builder: (BuildContext context) => CustomRoutePage()),'alias_route': (RouteSettings settings) => PageRouteBuilder(
         pageBuilder: (BuildContext context,Animation animation,Animation secondaryAnimation) =>
           CustomRoutePage(),),};
    
     ...
    
    }
    

    它会生成如下代码

    Map<String,RouteFactory> _customRoutePage = CustomRoutePage.route;

    自定义路由(优先级:2)

    这种方法自定义路由的优先级较低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。

    @RoutePage()
    class CustomRoutePage extends StatelessWidget {
     @PageRouteBuilderFuntcion()
     static Route buildPageRoute(RouteSettings settings) => PageRouteBuilder(
        pageBuilder: (BuildContext context,Animation secondaryAnimation) =>
          CustomRoutePage(),);
    
     ...
    
    }
    

    它会生成如下代码

    Map<String,RouteFactory> _customRoutePage = <String,RouteFactory>{
     'custom_route_page': CustomRoutePage.buildPageRoute,};
    

    自定义路由(优先级:1)

    这种方法自定义路由的优先级最低,如果同时存在多种自定义路由选择,则按优先级从大到小选择。

    @RoutePage()
    class CustomRoutePage extends StatelessWidget {
     // RoutePageBuilderFunction注解表明这个方法用来定义如何返回RoutePage
     // 它是可选的
     @RoutePageBuilderFunction()
     static Widget buildPage(BuildContext context,Animation secondaryAnimation,RouteSettings settings) =>
       CustomRoutePage();
    
     // RouteTransitionBuilderFunction注解表明这个方法用来定义如何应用动画过渡
     // 它是可选的
     @RouteTransitionBuilderFunction()
     static Widget buildTransitions(
         BuildContext context,Animation<double> animation,Animation<double> secondaryAnimation,Widget child,RouteSettings settings) =>
       child;
    
     // RouteTransitionDurationField注解表明这个字段用来定义页面过渡时常长,默认值为300 milliseconds
     // 它是可选的
     @RouteTransitionDurationField()
     static Duration transitionDuration = Duration(milliseconds: 400);
    
     ...
    
    }
    

    它会生成如下代码

    Map<String,RouteFactory>{
     'custom_route_page': (RouteSettings settings) => PageRouteBuilder(
        pageBuilder: (context,animation,secondaryAnimation) =>
          CustomRoutePage(),transitionsBuilder: (context,secondaryAnimation,child) =>
          CustomRoutePage.buildTransitions(
            context,child,settings),transitionDuration: CustomRoutePage.transitionDuration,};
    

    注意事项

    • 只允许有一个initalRoute
    • initalRoute会忽略自定义路由名,但会生成名为ROUTE_HOME的路由名称常量。
    • 所有自定义路由method或getter必须定义在路由所在类,且必须为static所修饰的和非私有的。
    • @H_502_19@

      最终生成代码

      最终生成文件名为FILENAME.route.dart

      其中FILENAME是被Router注解的App类所在的文件名。

      // GENERATED CODE - DO NOT MODIFY BY HAND
      
      // **************************************************************************
      // RouteGenerator
      // **************************************************************************
      
      import 'package:flutter/material.dart';
      import 'home_page.dart';
      import 'custom_route_page.dart';
      import 'custom_route_name_page.dart';
      import 'second_page.dart';
      import 'one_arguement_page.dart';
      import 'two_arguement_page.dart';
      
      const ROUTE_HOME = '/';
      const ROUTE_CUSTOM_ROUTE_PAGE = 'custom_route_page';
      const ROUTE_CUSTOM = 'custom';
      const ROUTE_SECOND_PAGE = 'second_page';
      const ROUTE_ONE_ARGUMENT_PAGE = 'one_argument_page';
      const ROUTE_TWO_ARGUMENT_PAGE = 'two_argument_page';
      
      RouteFactory onGenerateRoute = (settings) => Map.fromEntries([
         ..._home.entries,..._customRoutePage.entries,..._custom.entries,..._secondPage.entries,..._oneArgumentPage.entries,..._twoArgumentPage.entries,])[settings.name](settings);
      
      Map<String,RouteFactory> _home = <String,RouteFactory>{
       '/': (RouteSettings settings) => MaterialPageRoute(
          builder: (BuildContext context) => HomePage(),};
      Map<String,secondaryAnimation) =>
            CustomRoutePage.buildPage(
              context,RouteFactory> _custom = <String,RouteFactory>{
       'custom': (RouteSettings settings) => MaterialPageRoute(
          builder: (BuildContext context) => CustomRoutePageName(),RouteFactory> _secondPage = <String,RouteFactory>{
       'second_page': (RouteSettings settings) => MaterialPageRoute(
          builder: (BuildContext context) => SecondPage(),RouteFactory> _oneArgumentPage = <String,RouteFactory>{
       'one_argument_page': (RouteSettings settings) => MaterialPageRoute(
          builder: (BuildContext context) =>
            OneArgumentPage(title: settings.arguments),RouteFactory> _twoArgumentPage = <String,RouteFactory>{
       'two_argument_page': (RouteSettings settings) => MaterialPageRoute(
          builder: (BuildContext context) => TwoArgumentPage(
             title: (settings.arguments as Map<String,dynamic>)['title'],subTitle:
               (settings.arguments as Map<String,dynamic>)['subTitle'],};
      

      常见问题

      没有生成路由文件

      请检查是否添加了Router注解

      Example

      获取更详细信息,请参阅example

      以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

猜你在找的Android相关文章