I wrote short flutter app that have a async function that get value from cloud firestore and return Future bool type according to the information from the database. now in my main code I want to return a Widget according to the value that got return form that mention function, but I didn't succeed using the returned value right. I tried to write an external async function that will call the first function and will put the returned value inside a shared variable. but it didn't work for me and got sometimes error about that variable isn't been initialized.
it's looked like the code is not stopping line by line and wait for my function to return the value when been called and continue on the if statement.
Someone know how can I return a widget according to the value that the function returning and fix that issue?.
I tried using block of code using then but I never use it before so it doesn't worked as well.
my fist function:
Future<bool> firstFunc(String uid) async {
DocumentSnapshot userData =
await FirebaseFirestore.instance.collection('Users').doc(uid).get();
bool value = userData["param"];
return value;
}
and this is my main 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 bool sharedVar;
void getValue(String uid) async {
bool value = await firstFunc(uid);
sharedVar = value;
}
@override
Widget build(BuildContext context) {
if (_auth.currentUser != null) {
getValue(_auth.currentUser!.uid);
if (sharedVar == true)
{
return BossHomePage();
}
else {
return ClientHomePage();
}
} else {
return const EnterPhonePage();
}
}
}
CodePudding user response:
The reason it doesn't wait for getValue
is that getValue
is of type void
.
Try this;
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;
@override
Widget build(BuildContext context) {
if (_auth.currentUser != null) {
return FutureBuilder<bool>(
future: firstFunc(uid),
builder: (BuildContext context, snapshot){
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const CircularProgressIndicator();
case ConnectionState.none:
return const Text('No data');
case ConnectionState.active:
case ConnectionState.done:
if (snapshot.data == true) {
return BossHomePage();
} else {
return ClientHomePage();
}
default:
return const Text('No data');
}
},
)
} else {
return const EnterPhonePage();
}
}
}
CodePudding user response:
getValue
is a future method, You need to use async
at some point. You can convert this to
Future<bool> getValue(String uid) async {
bool value = ....;
return value;
}
And use FutureBuilder
(or initState
is better SatefullWidget) for this case
late bool sharedVar;
Future<void> getValue(String uid) async {
bool value =...;
sharedVar = value;
}
bool? currentUser;
_initData()async{
getValue("");
///all others methods
}
@override
void initState() {
super.initState();
_initData();
}
More about async-await
CodePudding user response:
Do this instead:
class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
final FirebaseAuth _auth = FirebaseAuth.instance;
late bool sharedVar;
void getValue(String uid) async {
bool value = await firstFunc(uid);
sharedVar = value;
}
@override
void initState() { // <--- add this
getValue(_auth.currentUser!.uid); // <-- move getValue here
super.initState();
}
@override
Widget build(BuildContext context) {
if (_auth.currentUser != null) {
if (sharedVar == true)
{
return BossHomePage();
}
else {
return ClientHomePage();
}
} else {
return const EnterPhonePage();
}
}
}
init function will help you to run code in the widget's startup.