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,
);
}
},
);
}
}