当用户注销时,FirebaseAuth.instance.onAuthStateChanged 不会触发流构建器

Sri*_*ath 5 firebase-authentication flutter

我的 Flutter 应用程序包含几个屏幕,如设置、添加产品、详细信息页面。

我在主页的流构建器中使用 FirebaseAuth.instance.onAuthStateChanged 来决定根据 onAuthStateChanged 更改显示登录或主页,如果用户在设置页面中并单击“FirebaseAuth.instance.signOut();”注销” ,应用程序停留在相同的设置页面上,并且不会重定向到我们在主页中使用的流构建器中提到的登录页面,如下所示。

MaterialApp(
          home: StreamBuilder(
            stream: FirebaseAuth.instance.onAuthStateChanged,
            builder: (ctx, snapSot) {
              if (snapSot.hasData) {
                return HomePage();
              } else
                return  LoginScreen();
            },
          ),),)
Run Code Online (Sandbox Code Playgroud)

包版本:

  • 提供者:^4.1.2
  • firebase_auth:^0.16.1

我的期望:

用户在哪个页面中,如果他退出,他必须被带到登录屏幕。由于我正在使用 Streambuilder,并且我已将流源提供为 onAuthStateChanged。

工作场景:

但是,当用户在主页屏幕中单击注销时,它会按预期工作,并且用户将被带到登录页面。

不工作场景:

如果用户在任何其他页面中,它不会重定向到登录页面。单击注销时,我可以在控制台中看到以下日志。

场景:用户导航:登录->首页->应用抽屉->设置页面->退出

I/flutter ( 6186): HomePage
I/flutter ( 6186): appDrawer
I/flutter ( 6186): Settings
I/flutter ( 6186): appDrawer
I/flutter ( 6186): logoutDialog
D/FirebaseAuth( 6186): Notifying id token listeners about a sign-out event.
D/FirebaseAuth( 6186): Notifying auth state listeners about a sign-out event.
Run Code Online (Sandbox Code Playgroud)

解决方法尝试使用 Stream:

主应用程序文件:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<UserAccount>.value(
      value: Authservice().user,
      child: MaterialApp(
        home: Wrapper(),
        onGenerateRoute: CustomRouter.generateRoute,
        initialRoute: homeRoute,
      ),
    );
  }
}

class Wrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<UserAccount>(context);
    print("user: $user");
    if (user == null)
      return LoginScreen();
    else
      return Dashboard();
  }
}
Run Code Online (Sandbox Code Playgroud)

认证服务文件:

Stream<UserAccount> get user {
    return _auth.onAuthStateChanged.map(_userFBAccount);
  }

UserAccount _userFBAccount(FirebaseUser user) {
    return user != null
        ? UserAccount(
            uid: user.uid,
           )
        : null;
  }

Future<void> logout() async {
    try {
      print("logout");
      await _auth.signOut();
    } catch (error) {
      print("logout $error");
    }
  }
Run Code Online (Sandbox Code Playgroud)

警报对话按钮代码

FlatButton(
                onPressed: () async {
                  Navigator.of(ctx).pop(); // to pop put the alert Dialogue
                  await _authservice.logout().then((value) {
                    if (Navigator.canPop(ctx)) Navigator.of(ctx).pop();
                  });
                },
                child: const Text("Yes"),
                shape: Border(
                  right: BorderSide(color: Colors.grey),
                ),
              ),
Run Code Online (Sandbox Code Playgroud)

我在这里遗漏了一些逻辑还是 Firebase_auth 插件 onAuthStateChanged 的​​问题?

谢谢

Ton*_*bye 5

用户注销时停留在“设置”屏幕上的原因可能是因为您的“设置”屏幕位于导航器中,该导航器是小部件树的子级MaterialApp

由于侦听 的流AuthStateChange也是 的子级MaterialApp,因此“流”和“设置”页面位于不同的小部件树中。

我建议您将您的移动StreamBuilder到上面MaterialApp。然后,“设置”页面也将能够侦听 AuthStateChanges。

StreamBuilder(
        stream: FirebaseAuth.instance.onAuthStateChanged,
        builder: (ctx, snapSot) {
          return MaterialApp(
             home: snapSot.hasData ? HomePage() : LoginScreen(),
          );
)
Run Code Online (Sandbox Code Playgroud)

这应该可以解决问题

作为替代方案,您还可以await注销事件,然后在用户注销后自动弹出页面。

例如

await _authObject.signOut.then((value) {
  if(Navigator.canPop)
    Navigator.of(context).pop;
});
Run Code Online (Sandbox Code Playgroud)