1

Does anyone know why i got the Failed assertion: boolean expression must not be null. If I had logged in and quit the app and open the app again i should be directly in the homescreen.

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

class MyApp extends StatefulWidget {

  // This widget is the root of your application.
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  bool userIsLoggedIn = false;

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

  getLoggedInState()async{
    await HelperFunction.getUserLoggedInSharedPreference().then((value){
      setState(() {
        userIsLoggedIn = value;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: userIsLoggedIn ? HomeScreen() : CompanyLoadingBar(),
    );
  }
}
serby
  • 41
  • 6

4 Answers4

2

If your 'value' here can become null - you get the error. To be safe change the line inside setState to:

userIsLoggedIn = value ?? false; 

it will set the bool to false if value is null

galloper
  • 813
  • 1
  • 9
  • 17
  • If I do this the error is gone but when I had logged in and run the app again it shows me the Sign In screen again – serby Aug 31 '20 at 10:51
  • It works because the value is null, this means that the problem is in how HelperFunction.getUserLoggedInSharedPreference() handles stuff inside of it - why does it return null in the first place? Nothing to do with understanding what a Future is, duh. – galloper Aug 31 '20 at 11:08
  • This is my HelperFunction part : ````static Future getUserLoggedInSharedPreference()async{ SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool (sharedPreferenceUserLoggedInKey); }```` – serby Aug 31 '20 at 14:18
  • Sorry about the late answer, I think the best solution here would be if check out the usage example on shared_preferences page and try to follow it in your code: https://pub.dev/packages/shared_preferences/example – galloper Sep 01 '20 at 18:18
0

Your issue most likely lies in this function where you're setting userIsLoggedIn to null. Ensure getUserLoggedInSharedPreference actually returns a boolean and not null.

  void getLoggedInState() async {
    final result = await HelperFunction.getUserLoggedInSharedPreference();
    if (result != null) {
      setState(() {
        userIsLoggedIn = result;
      });
    } else {
      print("result is null");
    }
  }
Benjamin
  • 5,783
  • 4
  • 25
  • 49
  • I have changed it but when I restart my app it shows me the sign in screen again and not the homescreen. – serby Aug 31 '20 at 14:17
  • Must be an issue with your shared preferences then. – Benjamin Aug 31 '20 at 14:33
  • This is my HelperFunction part : ````static Future getUserLoggedInSharedPreference()async{ SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool (sharedPreferenceUserLoggedInKey); }```` – serby Aug 31 '20 at 15:20
0

Your problem is that you are not waiting for your Future to resolve to an actual value.

This line:

userIsLoggedIn = value;

might not have been reached when your build method is called. Because it's async and you don't await it.

You can set a default value to userIsLoggedIn, maybe false, that will solve your immediate problem. But it will not solve your real problem, that your program logic is asynchronous.

You will probably want to build your app with at least one FutureBuilder.

See: What is a Future and how do I use it?

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Follow the link, read and understand it, then implement it for your code. If you have *specific* problems doing that, feel free to ask. – nvoigt Aug 31 '20 at 10:53
0

You have a global approach error. You combine traditional and async/await methods in this code:

getLoggedInState()async{
    await HelperFunction.getUserLoggedInSharedPreference().then((value){
      setState(() {
        userIsLoggedIn = value;
      });
    });
  }

If you use async/await you should not use then method.

To implement what you want you should use something like this:

...
@override
Widget build(BuildContext context) {
  return MaterialApp(
    debugShowCheckedModeBanner: false,
    home: FutureBuilder<bool>(
      future: HelperFunction.getUserLoggedInSharedPreference(),
      builder: (context,snapshot) {
        if (snapshot.hasData) {
          // Future is ready. Take data from snapshot
          userIsLoggedIn = snapshot.data; // bool value is here
          return userIsLoggedIn ? HomeScreen() : CompanyLoadingBar();
        } else {
          // Show progress while future will be completed
          return CircularProgressIndicator();
        }
      }
    ),
  );
}
...

And also check what value is returned from HelperFunction.getUserLoggedInSharedPreference(). It seems it returns null because I think you have no already saved value. So you need to specify the default value:

final value = await SharedPreferences.getInstance().readBool(name) ?? false;
BambinoUA
  • 6,126
  • 5
  • 35
  • 51