Flutter 一起使用 navigator 和 ChangeNotifierProvider 的最佳方法是啥

Posted

技术标签:

【中文标题】Flutter 一起使用 navigator 和 ChangeNotifierProvider 的最佳方法是啥【英文标题】:Flutter what is the best approach to use navigator and ChangeNotifierProvider togetherFlutter 一起使用 navigator 和 ChangeNotifierProvider 的最佳方法是什么 【发布时间】:2021-01-15 15:28:57 【问题描述】:

我是新手,这个问题可能是一个非常基本的问题。 我有一个 firebase 电话身份验证登录页面来实现这一点, 如果用户已登录,则导航到主页 否则,如果用户是新用户,则导航到注册页面

问题是,无论何时在提供者处更改值,消费者都会收到通知并重建构建方法。我将无法在构建方法中收听它们并返回 Navigator.of(context).pushNamed()。知道将 ChangeNotifierProvider 与侦听器和相应的页面导航一起使用的正确方法是什么?

我有如下的登录类和提供者类,

class LoginPage extends StatefulWidget 
  @override
  _LoginPageState createState() => _LoginPageState();


class _LoginPageState extends State<LoginPage> 
        @override
          Widget build(BuildContext context) 
            return ChangeNotifierProvider(
              create: (_) => LoginProvider(),
              child: Consumer<LoginProvider>(builder: (context, loginState, child) 
                return Scaffold(
                  ...
                  body: RaisedButton(
                  onPressed: **loginState.doLogin(_textController.text, context);**
                   ...
                )
              ),
           );
         
   

class LoginProvider with ChangeNotifier 
     bool _navigateToSignup = false;
     bool get navigateToSignup => _navigateToSignup;

    Future doLogin(String mobile, BuildContext context) async 
        FirebaseAuth _auth = FirebaseAuth.instance;
        _auth.verifyPhoneNumber(
          ...
          verificationCompleted: (AuthCredential credential) async 
          UserCredential result = await _auth.signInWithCredential(credential);
          User user = result.user;
          // if user is new user navigate to signup
          // do not want to use Navigator.of(context).pushNamed('/signupPage'); here, instead would like to notify listeners at login page view and then use navigator.
          if (user.metadata.creationTime == user.metadata.lastSignInTime) 
            _navigateToSignup = true;
           else 
            if (result.user != null) 
              _navigateToHome = true;
              //Navigator.of(context).pushNamedAndRemoveUntil('/homePage', ModalRoute.withName('/'));
             
          
          notifyListeners();
        ,
          ...
         );
    

提前致谢。

【问题讨论】:

【参考方案1】:

有多种方法,您可以选择最适合自己的一种。

    context 传递给ChangeNotifier,就像您已经在做的那样。我也不喜欢这样,但有些人会这样做。

    将回调传递给您的ChangeNotifier,当您需要导航时将调用该回调。此回调将由您的 UI 代码执行。

    与 2 相同,但不是回调,而是导出 Stream 并发出一个指示您需要导航的事件。然后,您只需在 UI 上收听 Stream 并从那里导航。

    为您的导航器使用GlobalKey 并将其传递给您的MaterialApp,这样您就可以在任何地方使用此密钥。更多详情here.

【讨论】:

谢谢,我想到了第三点并在下面尝试了.. 它有效.. LoginPage 低于 void _navigationController() _loginProvider.gotoHomePage.stream.listen((event) Navigator.of(context)。 pushNamed('/homePage') 和提供者将有 StreamController _gotoHomePage = StreamController(); StreamController get gotoHomePage => _gotoHomePage; 我通常选择选项 2,因为我不必处理流的复杂性,例如记住取消订阅和更复杂的代码......但所有选项都有它们的位置。

以上是关于Flutter 一起使用 navigator 和 ChangeNotifierProvider 的最佳方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

Navigator.push 可以和 Flutter 三元一起使用吗

flutter系列之:在flutter中使用导航Navigator

Flutter Navigator 弹出和异步多字段数据

Flutter:如何将 PageRoute Animation 与 Navigator.of(context).pushNamed 结合起来

Flutter:将命名路由与自定义页面路由构建器一起使用?

Flutter / Dart 使用具有后代和 Navigator 的 Scoped Model