flutter - Provider中的监听器如何在Flutter中工作?

标签 flutter dart flutter-provider

我正在使用提供程序包来处理来自不同位置的数据。对于这个问题,我创建了一个示例项目,其中包括一个显示“登录”按钮的欢迎屏幕,单击该按钮后,它会重定向到“登录屏幕”,在该屏幕上将有一个登录文本字段,但现在,我放置了一个按钮,用于单击 call 登录功能,该登录功能会通知侦听器。我还具有注销功能和 bool(boolean) 值,可以跟踪已登录状态。

这些函数和值驻留在lib文件夹的providers目录中的auth.provider.dart文件中。

import 'package:flutter/foundation.dart';

class Auth with ChangeNotifier {
  var _loggedIn = false;

  bool get loggedIn => _loggedIn;

  void loginUser() {
    _loggedIn = true;
    print('Logged in');
    notifyListeners();
  }

  void logout() {
    _loggedIn = false;
    print('Logged out');
    notifyListeners();
  }
}

我在main.dart中提供了提供程序,并且还在使用Consumer:
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Auth>(
      create: (_) => Auth(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: Consumer<Auth>(
          builder: (_, auth, __) {
            print('main.dart logged in: ${auth.loggedIn}');
            if(auth.loggedIn) return HomeScreen();
            return WelcomeScreen();
          },
        ),
        routes: {
          LoginScreen.routeName: (ctx) => LoginScreen(),
          HomeScreen.routeName: (ctx) => HomeScreen(),
        },
      ),
    );
  }
}

在上面的文件中,我只是检查loggedIn是否为true。如果未显示,则显示欢迎屏幕,以便用户可以登录,但是如果用户登录,则直接显示主屏幕。还已在消费者的构建器中放置了一条打印语句,以便每当收到有关身份验证数据的任何更改的通知时,它将打印状态。该程序在应用程序启动时运行一次,并且不再运行。

登录屏幕上没有什么东西,只有一个脚手架和一个调用登录功能的登录按钮。
RaisedButton(
    child: Text('Click to Login'),
    onPressed: () {
      Provider.of<Auth>(context, listen: false).loginUser();
    },
),

现在单击登录按钮时,它将loggedIn bool(boolean) 值设置为true并通知侦听器应为Consumer,但main.dart中的Consumer永远不会收到通知。它不会触发更改,有一种条件会检查登录是否为真,然后显示主屏幕,但屏幕完全不会更改。必须手动使用Navigator移到主屏幕,并且在主屏幕上有一个注销按钮,该按钮仅将loggedIn设置为false,一旦发生,它应该通知消费者,但又不会。

现在,这使我想到一个问题:提供程序中的侦听器如何工作?它何时通知侦听器更改?它是否不会通知更改是否发生在上层示例中,如上例中的Consumer处于main.dart中,并且更改发生在main.dart > WelcomeScreen > LoginScreen下2级。如何让main.dart中的使用者知道其使用的基础数据已更改?

如果要快速开始使用上面的示例,则here是存储库链接。

最佳答案

我经历了您的github代码。

使用pushReplacementNamed进入登录屏幕

Initially->main.dart->welcomeScreen->(on-clicking-loginbtn)->LoginScreen



这里,

1)消费者不在收听(因为您最初的main.dart屏幕已替换为登录页面,并且当前不存在于正在收听的页面上)

2)没有导航器可以返回(因为页面不在堆栈中而被替换)

使用pushNamed进入登录屏幕

Initially->main.dart->welcomeScreen->(on-clicking-loginbtn)->LoginScreen



这里,

1)消费者正在收听(因为您的主main.dart屏幕没有被替换并且当前存在于页面中。但是您没有看到更改,因为您已在堆栈的上方用登录屏幕覆盖了主初始页面)

2)有导航器可返回到主屏幕(现在您可以使用后退箭头返回以查看更改)

Conclusion Page will not able to listen to changed Provider Value if the page is replaced by other page. It should be there in a screen listening.



可以使用的模式

main.dart(主参数)
home: Consumer<Auth>(
          builder: (_, auth, __) {
            print('main.dart logged in: ${auth.loggedIn}');
            if(auth.loggedIn) return HomeScreen();
            return WelcomeScreen();
          },
        )

WelcomeScreen(登录代码)
 RaisedButton(
              child: Text('Login'),
              onPressed: () => Navigator.of(context).pushReplacementNamed(LoginScreen.routeName),
            )

LoginScreen(登录按钮)
RaisedButton(
          child: Text('Click to Login'),
          onPressed: () {
            Provider.of<Auth>(context, listen: false).loginUser();
            Navigator.of(context).pushReplacementNamed('/');
          },
        )

主屏幕(注销btn)
RaisedButton(
          child: Text('Logout'),
         onPressed: () {
            Provider.of<Auth>(context, listen: false).logout();
            Navigator.of(context).pushReplacementNamed('/');
          }

关于flutter - Provider中的监听器如何在Flutter中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62085582/

相关文章:

android-studio - Flutter 医生报告看到了两个 Android Studio 安装

dart - 在 flutter 中创建卡片和标题

dart - CustomScrollView 中的 Flutter float 操作按钮

dart - Dart 1.x 书籍仍然适用吗?

flutter - 如何使用 Provider/ChangeNotifier 在状态更改时让 TextFormField flutter ?

flutter - 在小部件上方找不到正确的提供商

Firebase 尚未正确初始化

ios - 我错误地将我的 iOS 应用程序(flutter) 连接到了错误的 firebase 项目,我可以更改 firebase 项目吗?

android - 如何解决这个 "Cannot enable MyLocation layer as location permissions are not granted"?

flutter - 如何在flutter中拥有相同数据类型的多个流提供者?