Flutter - 如何使用 Firebase Auth 在 streambuilder 中访问未来的价值

Flutter - how to access the value of a future inside a streambuilder, with Firebase Auth

我正在为我正在构建的基于订阅的应用程序使用 Firebase 身份验证,并使用云功能和自定义声明,我确保用户只有在订阅有效时才能登录。

我的应用程序有一个登陆页面,用于检查用户是否已登录,如果已登录,他们将被带到应用程序主页。如果没有,他们将显示登录屏幕。这是它的代码:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            if (user == null || user.emailVerified == false) {
              return SignInHomePage.create(context);
            }
            return Provider<User?>.value(
              value: user,
              child: DisclaimerAcceptanceHomeScreen(
                userName: user.displayName,
              ),
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

这非常适合获取用户数据并显示相关屏幕。唯一的问题是,我不知道如何将用户的订阅状态添加到此,以确保只有具有有效订阅的用户才会被定向到应用程序的主页。订阅状态自定义声明被 return 编辑为未来。理论上我想使用这样的东西:

  final idTokenResult =
      await FirebaseAuth.instance.currentUser?.getIdTokenResult(true);

然后:

idTokenResult?.claims!['status']

return 用户进入登录屏幕的理想情况是:

user == null || user.emailVerified == false || idTokenResult?.claims!['status'] != 'active'

这确实在 async/await 函数中起作用,但您会看到我的登录页面是一个无状态小部件并且不是异步的。

如何修改着陆页代码,以允许我获得 Future 'status' 自定义声明值?我将不胜感激对此的任何建议。谢谢!

您是否考虑过在对 getIdTokenResult 的调用周围使用 FutureBuilder

或者,您可以在 FirebaseAuth.instance.idTokenChanges() 上使用 StreamBuilder 来获得 ID 令牌所有更新的通知。

根据 Frank 的评论,我修改了我的 StreamBuilder 以包含 FutureBuilder,其中 future 是 getIdTokenResult(true) 函数。这就是上面的代码,按照描述进行了修改:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            return FutureBuilder<IdTokenResult>(
              future: user?.getIdTokenResult(true),
              builder: (
                BuildContext context,
                AsyncSnapshot<IdTokenResult> snapshotData,
              ) {
                if (user == null ||
                    user.emailVerified == false ||
                    snapshotData.data?.claims!['status'] != 'active') {
                  return SignInHomePage.create(context);
                } else {
                  return Provider<User?>.value(
                    value: user,
                    child: DisclaimerAcceptanceHomeScreen(
                      userName: user.displayName,
                    ),
                  );
                }
              },
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

这让我可以在允许用户访问应用程序之前检查用户的订阅状态。