每次刷新应用程序时都会触发 Flutter web Firebase onAuthStateChanges

Posted

技术标签:

【中文标题】每次刷新应用程序时都会触发 Flutter web Firebase onAuthStateChanges【英文标题】:Flutter web Firebase onAuthStateChanges gets triggered every time I refresh the app 【发布时间】:2020-12-29 05:36:09 【问题描述】:

我正在使用 Flutter Web 开发一个网络应用。

每次我刷新页面时,都会触发 onAuthStateChanges 并执行仅在身份验证状态发生更改时才应触发的功能。

这种行为是有意的吗?

为了订阅 onAuthStateChanges,我用一个有状态的小部件包装了我的主小部件并监听了 onAuthStateChanges,如下所示: Flutter Stream Builder Triggered when Navigator Pop or Push is Called

以下是我的代码:

我的包装:

/// Wrapper for stateful functionality to provide onInit calls in stateles widget
class StatefulWrapper extends StatefulWidget 
  final Function onInit;
  final Widget child;
  const StatefulWrapper(@required this.onInit, @required this.child);
  @override
  _StatefulWrapperState createState() => _StatefulWrapperState();


class _StatefulWrapperState extends State<StatefulWrapper> 
  @override
  void initState() 
    if (widget.onInit != null) 
      widget.onInit();
    
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return widget.child;
  

我在 main.dart 中的小部件:

Widget build(BuildContext context) 
    var router = MyRouter.Router();
    var authenticationService = locator<AuthenticationService>();
    var sharedPreferences = locator<SharedPreferencesService>();

    return StatefulWrapper(
      onInit: () 
        authenticationService.listenToAuthChanges();
      ,
      child: FutureBuilder(
          future: sharedPreferences.getSharedPreferences('ruolo'),
          builder: (context, snapshot) 
            return MaterialApp(
              builder: ExtendedNavigator<MyRouter.Router>(
                initialRoute: MyRouter.Routes.startupView,
                guards: [AuthGuard(), AdminGuard()],
                router: router,
                navigatorKey: locator<NavigationService>().navigatorKey,
              ),
              title: 'Flutter Demo',
              theme: ThemeData(
                primarySwatch: Colors.blue,
                visualDensity: VisualDensity.adaptivePlatformDensity,
              ),
              onGenerateRoute: router.onGenerateRoute,
            );
          ),
    );
  

这是来自 authenticationService 的方法:

  void listenToAuthChanges() 
    FirebaseAuth.instance.authStateChanges().listen((firebaseUser) async 
      if (firebaseUser == null) 
        navigationService.navigateTo(Routes.login);
       else 
         navigationService.replaceWith(Routes.home);
      
    );
  

当我在浏览器中刷新页面时,会触发此函数的侦听器,如果我没有登录,它会导航到登录,否则在主页上。

这是故意的吗?对我来说,只有当它收听的内容发生变化时,监听器才应该触发。

【问题讨论】:

如果您刷新页面,您实际上是在重新启动整个应用程序。这是有意的,否则你无法在启动时获得身份验证状态。 好吧,但是为什么会触发函数的handler呢?对我来说,这对我来说没有任何意义。 我的意思是,只有当该事件发生时才应该触发侦听器的处理程序。当我刷新时,我的登录状态没有改变,它和以前一样。 如果他们将其删除,则无法确定应用启动时的身份验证状态。当您刷新网页时,它不会“记住”之前的身份验证状态。您正在重新启动整个应用程序。 【参考方案1】:

当应用加载时,Firebase 会检查用户的身份验证状态。在该过程开始时,调用任何具有空值的活动身份验证状态侦听器。如果用户可以通过身份验证,则使用用户配置文件对象调用侦听器。

所以您所看到的确实按预期工作。

【讨论】:

我还有一个问题。使用我在这里显示的代码,触发器似乎被触发了不止一次。我想某处应该有一个错误,因为这不是故意的,对吧? 您的回调通常会在页面加载时使用null 调用,然后在稍后与实际用户一起调用。 感谢您的解释。但是,我注意到一种与您向我暴露的行为不同的行为。当我登录和注销时,只调用一次监听器。当我刷新我的页面时,会多次调用监听器,但如果我已登录,则会使用用户的值多次调用它。如果我没有登录,它会被多次调用为 null 。以下是刷新页面的示例: 触发了侦听器 - 时间戳:2020-09-11 09:17:53.741 电子邮件为:mail@mail.com 触发了侦听器 - 时间戳:2020-09-11 09:17:53.755 电子邮件为: mail@mail.com 我在移动设备上使用过 firebase,我喜欢它,但这种在网络上的行为让我很难过。由于我需要保存我的用户身份验证状态,我想使用监听器将他重定向到正确的页面。然而,监听器多次调用,使得网络应用程序有几个无用和烦人的重定向。解决这个问题的标准方法是什么?到目前为止,我在侦听器中没有任何重定向,但我 sed 了一个共享首选项(loggedIn),并且我有一个启动屏幕来检查这个变量并相应地重定向到它。但我觉得这是一种解决方法,而不是正确的方法。 我发现的另一个解决方案是检查 onAuthStateChange 中的时间戳。如果时间戳大于 500 毫秒,则进行导航。但我仍然认为这是一个肮脏的解决方法,而不是解决方案。

以上是关于每次刷新应用程序时都会触发 Flutter web Firebase onAuthStateChanges的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Page 每次在导航弹出时都会重新加载

React 上下文每次使用它时都会返回初始状态 - 尽管 setState

每次设置状态时都会调用 Flutter 函数

每次添加新项目时都会触发 RadListView SelectedIndexChanged

每次加载页面时都会触发 Graphql 查询。如何保存在缓存中?

AppWidgetProvider - 每次对任何 AppWidget 文件进行更改时都会触发 onUpdate 吗?