Home > Back-end >  ternary operator is not working as expected in flutter
ternary operator is not working as expected in flutter

Time:07-17

I have to render screens condition wise. but conditions are not getting fulfilled.

My function is always returns the false boolean value even if it doesn't have to.

Here is my code

class _HomePageState extends State<HomePage> {
  Future<bool> checkIsLoggedIn() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var data = await prefs.getString('isAuthenticated');

    // the value of data is true here
    print(data);
    if (data == "true") {
      return true;
    } else {
      return false;
    }
  }

  @override
  void initState() {
    super.initState();
    checkIsLoggedIn();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: checkIsLoggedIn() == true ? Profile() : LoginScreen());
        //error : checkIsLoggedin () function returns false in my case.
  }
}

CodePudding user response:

Use then() to wait for the Future. Then, assign the result with setState().

class _HomePageState extends State<HomePage> {
  Future<bool> checkIsLoggedIn() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var data = await prefs.getString('isAuthenticated');

    // the value of data is true here
    print(data);
    if (data == "true") {
      return true;
    } else {
      return false;
    }
  }

  var isLoggedIn = false; // HERE

  @override
  void initState() {
    super.initState();
    
    checkIsLoggedIn().then((result) {  // HERE
      setState(() {
        isLoggedIn = result;
      });
     
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: isLoggedIn == true  // HERE
          ? Profile() 
          : LoginScreen());
  }
}

CodePudding user response:

When getting into problems, I do recommend you are first looking into the warnings you are getting around the problematic area. If you are using a default Flutter project, you should have the lint unrelated_type_equality_checks activated since it is part of the Core set of Dart Lints:

DON'T Compare references of unrelated types for equality.

Comparing references of a type where neither is a subtype of the other most likely will return false and might not reflect programmer's intent.

enter image description here

The problem is that your checkIsLoggedIn() method have the following signature which means it returns an object of the type Future<bool>:

Future<bool> checkIsLoggedIn() async {

And you are then comparing this against true which are of the type bool. If you are doing an equality check against these two different types, it will ALWAYS end up returning false, which is also what you are observing.

A Future also means that you are handling a value that are potentially still not created. So when you are running your checkIsLoggedIn() == true it does not even know yet if the bool inside your Future<bool> are true or false.

The solution are to either make it so checkIsLoggedIn() returns bool, which cannot be done in this case since the method are handling asynchronously logic.

Another solution would then be to await the returned Future from checkIsLoggedIn(). But we cannot use await unless we mark the method, we are inside, as async. But for Flutter, we are not allowed to have build() marked as async.

So a solution would instead be to handle the asynchronously nature of checkIsLoggedIn() by using FutureBuilder:

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

Which are a Widget made for handling the building of the GUI when we don't know the value of the Future, but then triggers an automatic rebuild when the value of the Future are received.

CodePudding user response:

You can use .getbool instead .getString

To wait for checkIsLoggedIn result you can use a FutureBuilder.

Here an example :D

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  Future<bool> checkIsLoggedIn() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final isAuthenticated = await prefs.getBool('isAuthenticated');

    return isAuthenticated;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<bool>(
        future: checkIsLoggedIn(),
        builder: (context, snapshot) {

          // SHOW LOADING WHILE PREFS IS GETTING DATA
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }

          // SHOW SCREEN ACCORDING DATA
          return snapshot.data! //
              ? const Profile()
              : const LoginScreen();
        },
      ),
    );
  }
}
  • Related