Home > Net >  Flutter how to wait until Future function complete
Flutter how to wait until Future function complete

Time:03-13

I wrote a short flutter app that have a variable that need to be initialize before I send him to another function, so I wrote a function that initializing the variable as the app started. but for some reason the code isn't waiting for the function to end and I get the "LateInitializeError" error. Someone know how can I make the code wait until the function is finished and the variable has updated?.

this is my code:

// imports...

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

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

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: AuthenticationWrapper(),
    );
  }
}

class AuthenticationWrapper extends StatefulWidget {
  const AuthenticationWrapper({Key? key}) : super(key: key);
  @override
  _AuthenticationWrapperState createState() => _AuthenticationWrapperState();
}

class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  late Map<String, dynamic> data;

  @override
  void initState() {
    super.initState();
    getUserDataFunc().then((Map<String, dynamic> value) {
      data = value; // here I am updating the variable
    });
  }

  Future<Map<String, dynamic>> getUserDataFunc() async {
    return getUserData.getUserInfo("GGji5pJyJHQevdtlhqKDKjrVOwq1");
  }

  @override
  Widget build(BuildContext context) {
    if (_auth.currentUser != null) {
      return FutureBuilder<bool>(
        future: loginFunctions.isBarber(_auth.currentUser!.uid),
        builder: (BuildContext context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return const LoadingPage();

            case ConnectionState.none:
              return const Text("");

            case ConnectionState.active:
            case ConnectionState.done:
              if (snapshot.data == true) {
                return const BarberHomePage();
              } else {
                return ClientHomePage(
                  uid: _auth.currentUser!.uid,
                );
              }
          }
        },
      );
    } else {
      return ClientHomePage(
          uid: "GGji5pJyJHQevdtlhqKDKjrVOwq1", userData: data); // here I am want to send that variable, and I get the error
    }
  }
}

CodePudding user response:

The build function will run at least once before any async task. That means that ClientHomePage will always be built before data is initialized. I would just pass it as a future and have a future builder in ClientHomePage as well.

class AuthenticationWrapper extends StatefulWidget {
  const AuthenticationWrapper({Key? key}) : super(key: key);
  @override
  _AuthenticationWrapperState createState() => _AuthenticationWrapperState();
}

class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
  final FirebaseAuth _auth = FirebaseAuth.instance;


  Future<Map<String, dynamic>> getUserDataFunc() async {
    return getUserData.getUserInfo("GGji5pJyJHQevdtlhqKDKjrVOwq1");
  }

  @override
  Widget build(BuildContext context) {
    if (_auth.currentUser != null) {
      return FutureBuilder<bool>(
        future: loginFunctions.isBarber(_auth.currentUser!.uid),
        builder: (BuildContext context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return const LoadingPage();

            case ConnectionState.none:
              return const Text("");

            case ConnectionState.active:
            case ConnectionState.done:
              if (snapshot.data == true) {
                return const BarberHomePage();
              } else {
                return ClientHomePage(
                  uid: _auth.currentUser!.uid,
                );
              }
          }
        },
      );
    } else {
      return ClientHomePage(
          uid: "GGji5pJyJHQevdtlhqKDKjrVOwq1", userData: getUserDataFunc());
    }
  }
}


class ClientHomePage extends StatefulWidget {
  const ClientHomePage({Key? key, this.data}) : super(key: key);
  Future<Map<String, dynamic>> data;

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

class _ClientHomePageState extends State<ClientHomePage> {
  

  @override
  Widget build(BuildContext context) {
      return FutureBuilder<bool>(
        future: data,
        builder: (BuildContext context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return const LoadingPage();

            case ConnectionState.none:
              return const Text("");

            case ConnectionState.active:
            case ConnectionState.done:
                return ClientHomePageContent(
                  data: data,
                );
          }
        },
      );
  }
}
  • Related