0
点赞
收藏
分享

微信扫一扫

Flutter路由管理三方Fluro使用(一)

小猪肥 2021-10-04 阅读 82

对于Flutter路由的使用,从入门到深入一般有以下几个阶段:

  1. 初步了解到Flutter中是用路由(Route)表示页面(Page)。使用基本的MaterialPageRoute方式进行页面操作。
  2. 学会使用Navigator来完成路由操作。
  3. 学会使用命名路(Named Route)由来完成路由的管理与操作。
    以上三个阶段属于官方的基本知识。
  4. 使用三方Fluro完成路由的管理与操作。
  5. 使用注解方式完成路由的管理与操作。(闲鱼有三方)

首先假设我们的App组织架构如下

- login模块
- home模块
- buy模块
我们需要高效的管理现有页面路由,并兼顾后续页面扩展。
新建一个Flutter工程

在pubspec.yaml文件中添加Fluro三方

dependencies:
  flutter:
    sdk: flutter
  # 路由管理三方Fluro
  # https://github.com/theyakka/fluro
  fluro: ^1.6.3

.yaml文件对齐有严格要求
建议每个添加的三方库都附上简要说明和网址

修改基本代码

修改Home页面布局为中间一个按钮
添加一个Buy页面,布局也是中间一个按钮
源码lib1

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FlatButton(
          onPressed: () => print('进行跳转操作'),
          child: Text('点我 跳转到buy页面'),
        ),
      ),
    );
  }
}
根据作者的说明我们先初始化Router
final router = Router();

接下来我们浏览一下Router的源码,大致浏览都提供了哪些方法。
...假装看懂了,还是看作者说明吧。作者说明对新手也不怎么友好。。
好像有一行很短的样子,先看这一行。

You can also manually push to a route yourself. To do so:
router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);

翻看一下源代码

///
Future navigateTo(BuildContext context, String path,
      {bool replace = false,
      bool clearStack = false,
      TransitionType transition,
      Duration transitionDuration = const Duration(milliseconds: 250),
      RouteTransitionsBuilder transitionBuilder}) {
     ....
     return future;
  }
if (route != null) {
        if (clearStack) {
          future =
              Navigator.pushAndRemoveUntil(context, route, (check) => false);
        } else {
          future = replace
              ? Navigator.pushReplacement(context, route)
              : Navigator.push(context, route);
        }
        ...
      }

默认的clearStack是false,replace是false,那么
future = Navigator.push(context, route);
这就是非常基础的Navigator用法了。
context是直接传入的参数,那么route是如何得到呢。

RouteMatch routeMatch = matchRoute(context, path,
        transitionType: transition,
        transitionsBuilder: transitionBuilder,
        transitionDuration: transitionDuration);
    Route<dynamic> route = routeMatch.route;

可以看到通过传入path等参数,通过使用matchRoute方法,我们获得到了route。暂时不用关心该方法的内部,大概的也能猜到path就是我们使用命名路由,注册路由表时的路由名。此时我们还没有使用命名路由注册路由表。
让我们直接使用作者给我们的说明代码

router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);

看看报错信息

flutter: No registered route was found to handle '/users/1234'.
flutter: 进行跳转操作
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: 
No registered route was found to handle '/users/1234'
null

提示我们路由没有注册。这个提示是fluro给出的。
是否就是使用命名路由时的注册路由表呢?我们添加一下代码

routes: {
        '/users/1234': (context) => BuyPage(),
      },

错误依然存在。那么让我们来看看fluro说的registered在哪里执行。
查看fluro的源码

/// The tree structure that stores the defined routes
  final RouteTree _routeTree = RouteTree();
    ...
  /// Creates a [PageRoute] definition for the passed [RouteHandler].
 /// You can optionally provide a default transition type.
  void define(String routePath,
      {@required Handler handler, TransitionType transitionType}) {
    _routeTree.addRoute(
      AppRoute(routePath, handler, transitionType: transitionType),
    );
  }

可以看到作者的解释
RouteTree 用来存储已经定义的路由
difine方法创建PageRoute
那么我们需要调用define方法来定义(registered)路由。

Widget build(BuildContext context) {
    ...
    router.define('/users/1234', handler: XXX);
    ...
}

那么这个handler是什么呢?查看一下源码

class Handler {
  Handler({this.type = HandlerType.route, this.handlerFunc});
  final HandlerType type;
  final HandlerFunc handlerFunc;
}
...
typedef Widget HandlerFunc(
    BuildContext context, Map<String, List<String>> parameters);

Handler是构造成HandlerType.route类型的类,需要传入this.handlerFunc参数
HandlerFunc是一个Widget,是BuildContext context, Map<String, List<String>> parameters的typedef定义。因此,我们要传送一个BuildContext context, Map<String, List<String>> parametersHandler当参数。

让我们构造一个buyPageHandler,参考作者的代码,返回值是一个路由Wiget(BuyPage())

var buyPageHandler = Handler(
        handlerFunc: (BuildContext context, Map<String, dynamic> params) {
      return BuyPage();
    });

此时,修改路由定义代码

router.define('/users/1234', handler: buyPageHandler);

运行程序 查看代码
可以看到,点击HomePage的按钮已经正常能够跳转到BuyPage。

让我们回一下为了,实现跳转Fluro都做了哪些事情。
  1. 初始化了一个router
  2. 定义了一个buyPageHandler。可以传入params,返回一个route类型的Widget.
  3. 定义了一个router,需要传入name和handler两个参数
  4. 使用navigateTo,传入name,进行页面跳转。
    至此Fluro的最基本用法已经说明完毕。让我们回到最初的那个问题

如果我们想在BuyPage跳转到HomePage页面,那么刚才的4个步骤我们需要一个不落的重新一遍。重新就意味着可以抽离相同的代码。比如抽离route的初始化。

如果我们想在LoginPage页面也跳转到HomePage页面,那么步骤 2 3也可以抽离出来单独定义,从而进行复用。我们可以清晰的看到步骤 2 3是跳转目标页面的定义,而与到底从哪个页面跳转来无关。

如何进行抽离呢?作者的说明里有这么两句话。。

下篇继续写。。

举报

相关推荐

0 条评论