【问题标题】:Boolean expression must not be null?布尔表达式不能为空?
【发布时间】:2020-12-19 11:07:23
【问题描述】:

有谁知道为什么我得到了失败的断言:布尔表达式不能为空。 如果我已经登录并退出应用程序并再次打开应用程序,我应该直接在主屏幕中。

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

【问题讨论】:

  • 检查调用堆栈。如果尚未设置登录偏好怎么办?
  • @ThienLD 你能在你用代码显示的地方发布一个答案吗?

标签: database firebase flutter


【解决方案1】:

您有一个全局方法错误。您在这段代码中结合了 traditionalasync/await 方法:

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

如果您使用async/await,则不应使用then 方法。

要实现你想要的,你应该使用这样的东西:

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

还要检查从HelperFunction.getUserLoggedInSharedPreference() 返回的值。它似乎返回null,因为我认为您还没有保存的值。所以需要指定默认值:

final value = await SharedPreferences.getInstance().readBool(name) ?? false;

【讨论】:

    【解决方案2】:

    您的问题很可能在于您将userIsLoggedIn 设置为null 的这个函数。确保 getUserLoggedInSharedPreference 实际上返回一个布尔值而不是空值。

      void getLoggedInState() async {
        final result = await HelperFunction.getUserLoggedInSharedPreference();
        if (result != null) {
          setState(() {
            userIsLoggedIn = result;
          });
        } else {
          print("result is null");
        }
      }
    

    【讨论】:

    • 我已经更改了它,但是当我重新启动我的应用程序时,它再次显示登录屏幕而不是主屏幕。
    • 那么您的共享偏好肯定有问题。
    • 这是我的 HelperFunction 部分:static Future&lt;bool&gt; getUserLoggedInSharedPreference()async{ SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool (sharedPreferenceUserLoggedInKey); }
    【解决方案3】:

    您的问题是您没有等待 Future 解析为实际值。

    这一行:

    userIsLoggedIn = value;
    

    在调用您的构建方法时可能尚未到达。因为它是async 而你不是await

    您可以将默认值设置为userIsLoggedIn,也许false,这将解决您的直接问题。但这并不能解决你真正的问题,你的程序逻辑是异步的。

    您可能希望使用至少一个FutureBuilder 来构建您的应用程序。

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

    【讨论】:

    • 点击链接,阅读并理解它,然后为您的代码实现它。如果您对此有特定问题,请随时提出。
    【解决方案4】:

    如果您在此处的“值”可以变为 null - 您会收到错误消息。 为了安全起见,将 setState 中的行更改为:

    userIsLoggedIn = value ?? false; 
    

    如果 value 为 null,它会将 bool 设置为 false

    【讨论】:

    • 如果我这样做,错误就会消失,但是当我登录并再次运行应用程序时,它会再次显示登录屏幕
    • 之所以有效,是因为该值为 null,这意味着问题在于 HelperFunction.getUserLoggedInSharedPreference() 如何处理其中的内容 - 为什么它首先返回 null?与理解什么是未来无关,呵呵。
    • 这是我的 HelperFunction 部分:static Future&lt;bool&gt; getUserLoggedInSharedPreference()async{ SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool (sharedPreferenceUserLoggedInKey); }
    • 对不起,回答迟了,我认为最好的解决方案是查看 shared_preferences 页面上的用法示例并尝试在您的代码中遵循它:pub.dev/packages/shared_preferences/example
    猜你喜欢
    • 1970-01-01
    • 2021-06-06
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    • 2021-07-09
    相关资源
    最近更新 更多