首页 > 解决方案 > 是否可以在 Flutter Navigator 中添加中间件?

问题描述

如果我有经过身份验证的 Firebase 用户,我会进行以下检查

if(await FirebaseAuth.instance.currentUser() == null)
  Navigator.pushNamed(context, TheRegisterPage.routeName);
else
  Navigator.pushNamed(context, TheGroupManagementPage.routeName);

而且我希望每次调用 Navigator 以导航到新路线时都执行此检查。有没有类似中间件的东西或我可以用来实现这一目标的其他方法?

我确实在https://api.flutter.dev/flutter/widgets/RouteObserver-class.html找到了 RouteObserver 类,但我注意到它的 didPush() 不是异步的,所以我无法异步检查是否在推送路由之前,我有一个经过身份验证的用户。我不喜欢为每条路线写一张支票的想法,因为它们都是一样的。那么有没有办法用 Flutter Navigator 实现某种异步中间件呢?

标签: flutterfirebase-authentication

解决方案


这是一个应用程序的示例实现,您可以在DartPad中运行一个包装器Navigator,您可以使用它来有条件地推送,也就是说,根据身份验证状态检查导航到页面或其他页面所需的任何身份验证确认.

请注意,FirstRoute是 的子级AuthNavigator。将构造函数中的条件更改AuthNavigator为false,您将看到不同的导航。这里的关键是方法,以及从 中的静态方法pushConditionally访问它的能力。contextof(BuildContext)AuthNavigator

你可以做所有的条件检查async,你只需要根据你的特定需要替换我someCondition

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      title: 'Navigation Basics',
      home: AuthNavigator(
        someCondition: true,
        child: FirstRoute(),
      ),
    ),
  );
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            AuthNavigator.of(context).pushConditionally(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

class ThirdRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: Text("Third Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

class AuthNavigator extends StatefulWidget {
  const AuthNavigator(
      {@required this.child, @required this.someCondition, Key key})
      : super(key: key);

  final Widget child;
  final bool someCondition;

  static _AuthNavigatorState of(BuildContext context) =>
      context.findAncestorStateOfType<_AuthNavigatorState>();

  @override
  _AuthNavigatorState createState() => _AuthNavigatorState();
}

class _AuthNavigatorState extends State<AuthNavigator> {
  Future<T> pushConditionally<T extends Object>(
          BuildContext context, Route<T> route) =>
      widget.someCondition
          ? Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => ThirdRoute()),
            )
          : Navigator.push(
              context,
              route,
            );

  @override
  Widget build(BuildContext context) => widget.child;
}

如果您有任何疑问,请随时发表评论。


推荐阅读