Flutter Navigator 是否可以添加中间件?

Mik*_*ink 1 firebase-authentication flutter

我有以下检查我是否有经过身份验证的 Firebase 用户

if(await FirebaseAuth.instance.currentUser() == null)
  Navigator.pushNamed(context, TheRegisterPage.routeName);
else
  Navigator.pushNamed(context, TheGroupManagementPage.routeName);
Run Code Online (Sandbox Code Playgroud)

我希望每次调用导航器导航到新路线时都执行此检查。我可以使用中间件或其他方法来实现此目的吗?

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

dro*_*gel 6

以下是一个应用程序的示例实现,您可以在包装器的DartPadNavigator中运行该应用程序,您可以使用该包装器进行有条件推送,即检查需要导航到页面或其他页面的任何身份验证确认,具体取决于身份验证状态。

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

您可以执行所有条件检查async,只需someCondition根据您的特定需求替换 my 即可。

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;
}
Run Code Online (Sandbox Code Playgroud)

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