简体   繁体   English

如何让 streambuilder 等待?

[英]How to make streambuilder await?

I am build Flutter app with Firebase login but have issue with checking login status.我正在使用 Firebase 登录构建 Flutter 应用程序,但在检查登录状态时遇到问题。 On startup app must check if user logged in or not so it can show correct page.在启动应用程序时,必须检查用户是否登录,以便它可以显示正确的页面。 If logged in show homepage (different for different user role).如果登录显示主页(不同的用户角色不同)。 If not, show login page.如果没有,显示登录页面。

I am use StreamBuilder in RootPage of app for this but problem is app must first check user info with Firestore db so it know what type of user is logged in and then can route to correct page.为此,我在应用程序的 RootPage 中使用StreamBuilder ,但问题是应用程序必须首先使用 Firestore db 检查用户信息,以便它知道登录的用户类型,然后可以路由到正确的页面。 Problem is I no find way to make StreamBuilder wait for this function to check user info before move on.问题是我找不到让StreamBuilder在继续之前等待此函数检查用户信息的方法。 So the conditionals which operate on the values returned by function are not evaluate correctly.因此,对函数返回值进行操作的条件无法正确评估。 Here is code:这是代码:

    body: StreamBuilder<FirebaseUser>(
      stream: _auth.onAuthStateChanged,
      builder: (BuildContext context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return new SplashScreen();
        }
        if (snapshot.hasData && getUserDetailsComplete == true) {
          _getUserDetails();

          if (isAdmin == true) {
            return new AdminScreen();
          } else if (isAdmin == false) {
            return new HomeScreen();
          }
        } else {
          return new RootPage();
        }
      },
    ),
  );
}

You see I have make workaround for now by: 1. Return RootPage in else statement so it loop until one of conditionals is satisfied and 2. Set boolean to true when function _getUserDetails is complete and add to conditional so widget know when function is completed.您看,我现在已经通过以下方式制定了解决方法:1. 在 else 语句中返回 RootPage,以便它循环直到满足其中一个条件,以及 2. 在函数 _getUserDetails 完成时将布尔值设置为 true 并添加到条件中,以便小部件知道函数何时完成。 But this make app startup slow and not good style.但这会使应用程序启动缓慢且风格不佳。

Anyone know better way to do?有人知道更好的方法吗?

you can use .then and .getIdToken for user detail in token and claims您可以使用.then.getIdToken获取令牌和声明中的用户详细信息

Map<dynamic, dynamic> claims = {}; 
Auth.onAuthStateChanged.map((firebaseUser) {
  firebaseUser
      .getIdToken()
      .then((idTokenResult) => {
            if (idTokenResult.claims != null)
              {claims = idTokenResult.claims}
          })
      .catchError((e) => {print(e)});

more info about use custom claims for access control: firebase Doc有关使用自定义声明进行访问控制的更多信息: firebase Doc

You can use a StatefulWidget.您可以使用 StatefulWidget。 In the state of your widget, include a Widget object.在您的小部件状态中,包含一个小部件对象。 In initState , you can store a placeholder Widget (a CircularProgressINnc, or something), and call a function that does some checking in Firebase.initState中,您可以存储一个占位符 Widget(一个 CircularProgressINnc 或其他东西),并调用一个在 Firebase 中进行一些检查的函数。 Make sure this function is async , since it does networking, which has to be done on a separate thread.确保此函数是async的,因为它进行联网,这必须在单独的线程上完成。 At the end of this function, just call setState and replace the placeholder widget with a widget of choice.在此函数结束时,只需调用 setState 并将占位符小部件替换为所选小部件。 It would look something like this:它看起来像这样:

class MyScreen extends StatefulWidget {

  @override
  _MyScreenState createState() => _MyScreenState();
}

class _MyScreenState extends State<MyScreen> {
  Widget _screen;

  @override
  void initState() {
    _screen = CircularProgressIndicator();

    _doSomeFirebaseChecking();
  }

  void _doSomeFirebaseChecking() async {
    // Add your code that performs checks at Firebase here.

    // Then use setState to update the widget to a screen of choice.
    setState(() {
      if (isAdmin == true) {
        _screen = AdminScreen();
      } else if (isAdmin == false) {
        _screen = HomeScreen();
      }
    });
  }
}

In a similar application I wrote, I had to build widgets in a screen based on the content of some web API.在我编写的类似应用程序中,我必须根据某些 Web API 的内容在屏幕中构建小部件。 I used a method similar to this, and it works like a charm.我使用了与此类似的方法,效果非常好。

I hope this helps!我希望这有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM