颤振中的异步执行问题

时间:2020-06-22 12:29:01

标签: flutter async-await future

在下面的代码中,在第18行执行时调用了将来的函数readData(),在其完全执行之前将其移至第19行,即print语句。我想在调用readData()函数之后等待该函数完成其执行并更新flag变量,然后再进行进一步执行后

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/cupertino.dart';
import 'package:udharibook/Screens/SignInPage.dart';
import 'package:udharibook/Screens/UserProfile.dart';
import 'package:udharibook/Screens/dashboard.dart';

class AuthService  {
  bool flag = false;
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final DBRef = FirebaseDatabase.instance.reference().child('Users');

    handleAuth(){
    return StreamBuilder(
      stream: FirebaseAuth.instance.onAuthStateChanged,
      builder: (BuildContext, snapshot) {
        if(snapshot.hasData) {
         readData();
          print(flag);
          if(flag ==true)
            return DashboardPage();
          else
            return UserProfile();
        }
        else {
          return SignIn();
        }
      },
    );
  }

  Future<void> readData() async {
    final FirebaseUser user = await _auth.currentUser();
    final userid = user.uid;
    DBRef.child(userid).once().then((DataSnapshot data){
      print(userid);
      if(data.value!=null)
        {
          flag =  true;
          print(data.key);
          print(data.value);
        }
      else{
        print('User not found');
        flag = false;
      }
    });
  }

  signOut(){
    FirebaseAuth.instance.signOut();
  }

  signIn(AuthCredential authCreds){
    FirebaseAuth.instance.signInWithCredential(authCreds);
  }

  signInWithOTP(smsCode,verId){
    AuthCredential authCreds = PhoneAuthProvider.getCredential(
        verificationId: verId,
        smsCode: smsCode
    );
    signIn(authCreds);
  }
}

1 个答案:

答案 0 :(得分:1)

使用FutureBuilder,让您的readData返回true或false,而不是设置变量。

return StreamBuilder(
  stream: FirebaseAuth.instance.onAuthStateChanged,
  builder: (BuildContext, snapshot) {
    if(snapshot.hasData) {
      return FutureBuilder<String>(
        future: readData(), 
        builder: (BuildContext context, AsyncSnapshot<String> readDataSnapshot) {
          //readDataSnapshot.data will be your true/false from readData()
          if(readDataSnapshot.hasData){
            if(readDataSnapshot.data == true)
              return DashboardPage();
            else
              return UserProfile();
          } else {
            return CircularProgressIndicator(); // or something else while waiting for the future to complete.
          }
        }
      ); 
    } else {
      return SignIn();
    }    
  },
);
Future<bool> readData() async {
    final FirebaseUser user = await _auth.currentUser();
    final userid = user.uid;
    DBRef.child(userid).once().then((DataSnapshot data){
      print(userid);
      if(data.value!=null)
        {
          print(data.key);
          print(data.value);
          return true;
        }
      else{
        print('User not found');
        return false;
      }
    });
  }