annotation_route 的应用

本文介绍如何使用annotation_route包简化Flutter中的动态路由管理,通过注解实现路由映射,避免大量页面导入,提供一种配置化且低耦合的解决方案。

在flutter中,动态路由显得特别碎片化不易于管理,而且在页面中如果需要跳转到另外个页面的话,就需要把需要的页面引入进来,如果需要跳100个页面,就需要引100个进来,这样无疑显得太过庞大了。因此这里需要一个类似于配置化的结构并且又要缩小耦合性。

这里用到了annotation_route,这是闲鱼推出的一个以注解法实现flutter路由映射的包,详情演变过程看这里Flutter路由管理代码这么长长长长长,阿里工程师怎么高效解决?

本文记录记录在使用过程中踩过得一些坑。

首先在 pubspec.yaml 中引入annotation_route

需要跳转的页面引入annotation_route,并且在最前面定义@ARoute

然后在lib下新建一个router文件夹,内部建立一个管理路由的入口文件,名字可以随便取,这里叫route.dart。并写入如下代码

import 'package:annotation_route/route.dart';
import './route.internal.dart';
import 'package:flutter/material.dart';
@ARouteRoot()
class MyRouteOption {
  String urlpattern;
  Map<String, dynamic> query;
  MyRouteOption(this.urlpattern, this.query );
}
class AppRoute {
  static Widget getPage(String urlString, Map<String, dynamic> query) {
      ARouterInternalImpl internal = ARouterInternalImpl();
      ARouterResult routeResult = internal.findPage(ARouteOption(urlString, query), MyRouteOption(urlString, query));
      if(routeResult.state == ARouterResultState.FOUND) {
        return routeResult.widget;
      }
      return Scaffold(   // 这里只是例子,返回的是未匹配路径的控件
        appBar: AppBar(),
        body: Center(
          child: Text('NOT FOUND'),
        ),
      );
  }
}

现在写进去还会报错,因为还没找到route.internal.dart文件。

接下来运行

flutter packages pub run build_runner build --delete-conflicting-outputs

如果需要清除之前的文件可以运行

flutter packages pub run build_runner clean

如果之前没有引入build_runner的话这会报错,只需要在dev_dependencies中引入即可。

接下来它就会自动去找标了@ARoute注解的文件,然后在route.dart的同级目录下生成route.internal.dart。这个文件下已经定义好路径跳转的页面。

接下来就可以使用了,这里从main.dart跳转到newPage.dart页面。

由于是动态路由,现在newPage.dart中写入传进来的参数。

现在在main.dart引入route.dart并用AppRoute.getPage方法

getPage方法第一个参数就是之前定义的路径,第二个是传递的Map类型的参数。

在newPage.dart中接收参数,代码如下

import 'package:flutter/material.dart';
import 'package:annotation_route/route.dart';

@ARoute(url: 'page://newPage')
class NewPage extends StatelessWidget {
  NewPage(this.option); // 定义传入进来的参数
  // option是route.dart中定义的MyRouteOption类,从query获取传递的数据
  dynamic option;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text(option.query[ 'test' ]),
      ),
    );
  }
}

option.query中即可获取之前传递的参数。

这是annotation_route的基本用法,另外还提供别名等其他用法,由于没有用到就没有涉及。从上面的例子可以看到annotation_route只提供了一个类似于ImageProvider寻找资源这种用法,而不是局限于页面路由,因此也可以用来数据路由等。因此我在前面加上了"page://",因此根据自己的需要可以在route.dart中AppRoute做扩展。

 

 

File E:\AAAshixunruanjian\Lib\site-packages\fastapi\routing.py:994, in APIRouter.api_route.<locals>.decorator(func) 993 def decorator(func: DecoratedCallable) -> DecoratedCallable: --> 994 self.add_api_route( 995 path, 996 func, 997 response_model=response_model, 998 status_code=status_code, 999 tags=tags, 1000 dependencies=dependencies, 1001 summary=summary, 1002 description=description, 1003 response_description=response_description, 1004 responses=responses, 1005 deprecated=deprecated, 1006 methods=methods, 1007 operation_id=operation_id, 1008 response_model_include=response_model_include, 1009 response_model_exclude=response_model_exclude, 1010 response_model_by_alias=response_model_by_alias, 1011 response_model_exclude_unset=response_model_exclude_unset, 1012 response_model_exclude_defaults=response_model_exclude_defaults, 1013 response_model_exclude_none=response_model_exclude_none, 1014 include_in_schema=include_in_schema, 1015 response_class=response_class, 1016 name=name, 1017 callbacks=callbacks, 1018 openapi_extra=openapi_extra, 1019 generate_unique_id_function=generate_unique_id_function, 1020 ) 1021 return func File E:\AAAshixunruanjian\Lib\site-packages\fastapi\routing.py:933, in APIRouter.add_api_route(self, path, endpoint, response_model, status_code, tags, dependencies, summary, description, response_description, responses, deprecated, methods, operation_id, response_model_include, response_model_exclude, response_model_by_alias, response_model_exclude_unset, response_model_exclude_defaults, response_model_exclude_none, include_in_schema, response_class, name, route_class_override, callbacks, openapi_extra, generate_unique_id_function) 929 current_callbacks.extend(callbacks) 930 current_generate_unique_id = get_value_or_default( 931 generate_unique_id_function, self.generate_unique_id_function 932 ) --> 933 route = route_class( 934 self.prefix + path, 935 endpoint=endpoint, 936 response_model=response_model, 937 status_code=status_code, 938 tags=current_tags, 939 dependencies=current_dependencies, 940 summary=summary, 941 description=description, 942 response_description=response_description, 943 responses=combined_responses, 944 deprecated=deprecated or self.deprecated, 945 methods=methods, 946 operation_id=operation_id, 947 response_model_include=response_model_include, 948 response_model_exclude=response_model_exclude, 949 response_model_by_alias=response_model_by_alias, 950 response_model_exclude_unset=response_model_exclude_unset, 951 response_model_exclude_defaults=response_model_exclude_defaults, 952 response_model_exclude_none=response_model_exclude_none, 953 include_in_schema=include_in_schema and self.include_in_schema, 954 response_class=current_response_class, 955 name=name, 956 dependency_overrides_provider=self.dependency_overrides_provider, 957 callbacks=current_callbacks, 958 openapi_extra=openapi_extra, 959 generate_unique_id_function=current_generate_unique_id, 960 ) 961 self.routes.append(route) File E:\AAAshixunruanjian\Lib\site-packages\fastapi\routing.py:554, in APIRoute.__init__(self, path, endpoint, response_model, status_code, tags, dependencies, summary, description, response_description, responses, deprecated, name, methods, operation_id, response_model_include, response_model_exclude, response_model_by_alias, response_model_exclude_unset, response_model_exclude_defaults, response_model_exclude_none, include_in_schema, response_class, dependency_overrides_provider, callbacks, openapi_extra, generate_unique_id_function) 551 self.response_fields = {} 553 assert callable(endpoint), "An endpoint must be a callable" --> 554 self.dependant = get_dependant(path=self.path_format, call=self.endpoint) 555 for depends in self.dependencies[::-1]: 556 self.dependant.dependencies.insert( 557 0, 558 get_parameterless_sub_dependant(depends=depends, path=self.path_format), 559 ) File E:\AAAshixunruanjian\Lib\site-packages\fastapi\dependencies\utils.py:285, in get_dependant(path, call, name, security_scopes, use_cache) 283 for param_name, param in signature_params.items(): 284 is_path_param = param_name in path_param_names --> 285 param_details = analyze_param( 286 param_name=param_name, 287 annotation=param.annotation, 288 value=param.default, 289 is_path_param=is_path_param, 290 ) 291 if param_details.depends is not None: 292 sub_dependant = get_param_sub_dependant( 293 param_name=param_name, 294 depends=param_details.depends, 295 path=path, 296 security_scopes=security_scopes, 297 ) File E:\AAAshixunruanjian\Lib\site-packages\fastapi\dependencies\utils.py:482, in analyze_param(param_name, annotation, value, is_path_param) 476 use_annotation_from_field_info = get_annotation_from_field_info( 477 use_annotation, 478 field_info, 479 param_name, 480 ) 481 if isinstance(field_info, params.Form): --> 482 ensure_multipart_is_installed() 483 if not field_info.alias and getattr(field_info, "convert_underscores", None): 484 alias = param_name.replace("_", "-") File E:\AAAshixunruanjian\Lib\site-packages\fastapi\dependencies\utils.py:115, in ensure_multipart_is_installed() 113 except ImportError: 114 logger.error(multipart_not_installed_error) --> 115 raise RuntimeError(multipart_not_installed_error) from None RuntimeError: Form data requires "python-multipart" to be installed. You can install "python-multipart" with: pip install python-multipart
06-12
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值