Flutter 当用户注销时,FirebaseAuth.instance.onAuthStateChanged未触发流生成器

Flutter 当用户注销时,FirebaseAuth.instance.onAuthStateChanged未触发流生成器,flutter,firebase-authentication,Flutter,Firebase Authentication,我的颤振应用程序包含一些屏幕,如设置、添加产品、详细信息页面 我正在主页流生成器中使用FirebaseAuth.instance.onAuthStateChanged来决定基于onAuthStateChanged更改显示登录或主页,前提是用户在设置页面中并单击注销,即“FirebaseAuth.instance.signOut();”,应用程序保持在相同的设置页面上,不会重定向到我们在主页中使用的stream builder中提到的登录页面,如下所示 MaterialApp(

我的颤振应用程序包含一些屏幕,如设置、添加产品、详细信息页面

我正在主页流生成器中使用FirebaseAuth.instance.onAuthStateChanged来决定基于onAuthStateChanged更改显示登录或主页,前提是用户在设置页面中并单击注销,即“FirebaseAuth.instance.signOut();”,应用程序保持在相同的设置页面上,不会重定向到我们在主页中使用的stream builder中提到的登录页面,如下所示

MaterialApp(
          home: StreamBuilder(
            stream: FirebaseAuth.instance.onAuthStateChanged,
            builder: (ctx, snapSot) {
              if (snapSot.hasData) {
                return HomePage();
              } else
                return  LoginScreen();
            },
          ),),)
软件包版本:

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();
  }
}
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");
    }
  }
  • 提供程序:^4.1.2
  • firebase_认证:^0.16.1
我的期望:

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();
  }
}
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");
    }
  }
无论用户在哪个页面,如果他注销,他都必须进入登录屏幕。因为我正在使用 Streambuilder和我已经提供了onAuthStateChanged的流源

工作场景:

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();
  }
}
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");
    }
  }
但是,当用户在主页屏幕中单击注销时,其工作与预期一样,用户将进入登录页面

不工作场景:

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();
  }
}
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");
    }
  }
如果用户位于任何其他页面,则不会重定向到登录页面。单击注销时,我可以在控制台中看到以下日志

场景:用户导航:登录->主页->应用程序抽屉->设置页面->注销

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.
尝试使用流解决问题:

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();
  }
}
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");
    }
  }
主应用程序文件:

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();
  }
}
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");
    }
  }
我是否遗漏了一些逻辑,或者这是Firebase_auth插件onAuthStateChanged的问题


谢谢

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

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

我建议您将
StreamBuilder
移动到
MaterialApp
上方。 然后,设置页面还可以侦听AuthStateChanges

StreamBuilder(
        stream: FirebaseAuth.instance.onAuthStateChanged,
        builder: (ctx, snapSot) {
          return MaterialApp(
             home: snapSot.hasData ? HomePage() : LoginScreen(),
          );
)
这应该可以解决问题

或者,您也可以
等待
注销事件,然后在用户注销后自动弹出页面

e、 g


按照您提供的使用StreamBuilder包装MaterialApp的代码片段进行了尝试,但行为仍然相同。当我尝试从“设置”页面注销时,它仍然停留在“设置”页面。另外,我还需要等待_authObject.signOut。好的,在注销后,当你从“设置”页面按“后退”时,它是否会将你带到“登录”页面?更新了我的帖子,我使用了更多的代码示例。否,它关闭我的应用程序并转到android主屏幕。我在日志中注意到,在我按下signout后,再次调用了settings page build方法。好的,在注销后删除异步任务(弹出上下文的任务),然后查看注销后该任务的功能。然后从设置屏幕按back,删除pops代码并重试。还是同样的行为,它关闭我的应用程序并进入android主屏幕。我有一个类似的问题,我刚才解决了。请参阅@Nolence Thank将尝试并查看它。@Nolence,能够用您在给定链接中提到的方法解决我的问题,非常感谢。有没有一种方法可以解决这个问题,使用一个全局导航键,从主应用程序到所有路线导航都使用这个服务?因此,当用户注销时,它会从应用程序中的任何页面转到Auth页面。我不确定,因为我没有尝试过,但如果您找到其他解决方案,请随时通知我。不得不添加Willposcope小部件一直困扰着我,我不怀疑有更干净的解决方案。这些问题解决了吗?