Home > Net >  How to use Future<bool> return value from function without async function (Flutter)
How to use Future<bool> return value from function without async function (Flutter)

Time:02-23

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.

  • Related