【问题标题】:Is is correct to use Future builder inside a streambuilder in Flutter在 Flutter 的流构建器中使用 Future 构建器是正确的
【发布时间】:2020-11-26 22:34:31
【问题描述】:

我的要求是,每当用户使用电话号码进行验证时,它都会在 Firebase 中检查设置为用户电话号码的文档 ID(如果之前登录过)是否存在,如果存在则转到主页然后不会导航到 AccountVerification 页面。

另外,如果用户已经登录但没有验证关闭应用再打开应用,那么有两种情况,一种是用户验证了帐户详细信息,或者在验证过程中没有验证。在这种情况下,我将检查设置为用户电话号码的文档 ID 是否存在(如果存在),然后转到 HomePage 否则 AccountVerification 页面。 这是我的代码,它不能完美运行。任何人都可以建议我什么应该是正确的方法

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  var globalNumber;
  var Number;
  Firestore firestore = Firestore.instance;


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getCurrentUser();



  }

  @override
  Widget build(BuildContext context) {
    print(globalNumber);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: StreamBuilder<Object>(
        stream: FirebaseAuth.instance.onAuthStateChanged,
          builder: (BuildContext context, snapshot) {
            if (snapshot.hasData) {
              return FutureBuilder(
                  future: Future.wait([

                    firestore.collection('users').document(globalNumber).get()

                  ]),
                  builder: (BuildContext context,
                      AsyncSnapshot<List> snapshot) {
                    DocumentSnapshot doc = snapshot.data[0];
                    if(snapshot.hasData) {
                      if (doc.exists) {
                        return HomePage();
                      }
                      return AccountDetialsPage();
                    }
                    else{
                      return Container(child: Text('Loading'));
                    }
                  }
              );
            } else {
              return Phoneverification();
            }
          }),
    ) ;
  }

  getCurrentUser() async{

    final FirebaseAuth _auth = FirebaseAuth.instance;
    final FirebaseUser user = await _auth.currentUser();
    final uid = user.uid;
    globalNumber = user.phoneNumber;
    
    // Similarly we can get email as well
    //final uemail = user.email;
    print(uid);

  }

}

【问题讨论】:

  • 我的评论解决了你的问题吗?我正在寻找一些反馈,因为我刚开始在 StackOverflow 上帮助其他人!
  • 您好,我已经将答案标记为正确......是的,它有帮助......非常感谢

标签: flutter dart google-cloud-firestore firebase-authentication


【解决方案1】:

它不能正常工作,正如它所记录的那样:

“未来一定是更早获得的,例如在 State.initState、State.didUpdateConfig 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,不能在 State.build 或 StatelessWidget.buildmethod 调用期间创建它。如果 Future 与 FutureBuilder 是同时创建的,那么每次 FutureBuilder 的 parent 重建时,异步任务都会重新启动。”

这意味着当你的未来方法返回一个值时,会发生重建,触发另一个重建。这会创建一个循环。

您应该在initState() 上调用您的未来函数,然后使用该变量在构建方法中使用 FutureBuilder。例如:

    void main() {
      runApp(MyApp());
    }

    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }

    class _MyAppState extends State<MyApp> {

      var globalNumber;
      var Number;
      var user;
      Firestore firestore = Firestore.instance;


      @override
      void initState(){
         super.initState();
         getCurrentUser();
      }


      Widget build(BuildContext context){
        return return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: StreamBuilder<Object>(
          stream: FirebaseAuth.instance.onAuthStateChanged,
          builder: (BuildContext context, snapshot) {
            if (snapshot.hasData) {
              return FutureBuilder(
                  future: user,
                  builder: (BuildContext context,
                      AsyncSnapshot<List> snapshot) {
                    DocumentSnapshot doc = snapshot.data[0];
                    if(snapshot.hasData) {
                      if (doc.exists) {
                        return HomePage();
                      }
                      return AccountDetialsPage();
                    }
                    else{
                      return Container(child: Text('Loading'));
                    }
                  }
              );
            } else {
              return Phoneverification();
            }
        }),
      );
    }

    getCurrentUser() async{

      final FirebaseAuth _auth = FirebaseAuth.instance;
      final FirebaseUser user = await _auth.currentUser();
      final uid = user.uid;
      globalNumber = user.phoneNumber;
    
      // Similarly we can get email as well
      //final uemail = user.email;
      print(uid);
    
      getUserNumber(uid);
    }

    //Make another function that you insert into the getCurrentUser(), like this:
    
    getUserNumber(int uid){
      user = Future.wait([
      firestore.collection('users').document(globalNumber).get()
    ]);
  }

【讨论】:

  • 我对 Flutter 完全不熟悉......你能告诉我代码吗......我被困在这个页面上
  • 对不起,发布时没有进一步的代码编辑。看看这是否能解决您的问题。
  • @override void initState(){ super.initState(); x = Future.wait([ firestore.collection('users').document(globalNumber).get() ]); .... 这里当调用 init 函数时,我还没有 globalNumber,因为在我之前在 init 函数中的代码中,我调用了获取当前用户,然后从那里获取了用户号......如何解决我的意思是,当应用程序启动时,会调用 init 并且该数字尚未分配给 globalNumber 变量......另外,未来的“x”数据类型应该是什么??????
  • 更新了答案,以便您可以链接这两个事件。现在,您从 Future.await() 获得的值存储在一个类变量中。
  • 类似于 user13891541:initState 不是异步函数。所以你的意思是在 initState 中获得未来并在构建期间提供未来?我意识到我想潜在地将提供未来的函数转换为 Stream,因为如果返回值发生变化,我希望状态发生变化
猜你喜欢
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-08-12
  • 2019-05-09
  • 2020-05-01
  • 2020-12-12
  • 2020-03-27
  • 2021-11-11
相关资源
最近更新 更多