【问题标题】:Flutter - How can I retrieve a bool from an external function?Flutter - 如何从外部函数中检索布尔值?
【发布时间】:2022-01-13 14:38:17
【问题描述】:

我正在尝试查找登录用户是管理员还是普通用户。 我已经创建了一个全局函数(然后在 initState 中调用它)来检查角色是否为管理员,方法是将 bool 设置为 true 或 false,如下所示:

bool isAdmin;
  _checkRole() async {
    var firebaseUser = FirebaseAuth.instance.currentUser;
    await FirebaseFirestore.instance
        .collection("users")
        .doc(firebaseUser.uid)
        .get()
        .then((value) {
      if ((value.data()['role']) == 'admin') {
        isAdmin = true;
      } else {
        isAdmin = false;
      }
      return isAdmin;
    });
  }

我在抽屉里做了以下事情:

          isAdmin
              ? buildListTile(
                  'Admin Panel', Icons.admin_panel_settings_sharp, () {
                  Navigator.of(context).pushNamed(AdminScreen.routeName);
                })
              : buildListTile('User dashboard', Icons.person, () {}),

但是当我打开抽屉时,我收到Failed assertion: boolean expression must not be null 关于如何解决此问题的任何想法?

谢谢。

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    简答:
    isAdmin 在您构建 ListTile 时未初始化,因为异步函数还没有机会完成运行。

    更长的答案:
    您的 build 方法与其余代码同步发生,这意味着它逐行发生。您的 _checkRole() 方法是异步发生的,这意味着它会在任何时候找到它。因此,当您尝试在 initState 方法中初始化 isAdmin 时,它正在运行网络调用(这在程序时间方面需要很长时间)并等待网络调用完成以设置 isAdmin。同时,您的构建正在运行并尝试构建,但不知道它应该等待设置isAdmin

    解决方案:
    (注意,有很多方法可以解决这个问题,这只是一种)
    使用 FutureBuilder 或 StreamBuilder 加载变量并将变量类型设置为 Future 或流的等效项,并监听状态变化并相应地构建您的 UI。

    这是一个基本示例。仔细复制/粘贴。我没有运行代码。这只是一般的想法。

    Future<bool> isAdmin;
    
    FutureBuilder<String>(
      future: Globals.isAdmin,
      builder: (BuildContext context, AsyncSnapshot<Bool> snapshot) {
        if (snapshot.hasData) { //
          var isAdmin = snapshot.data;
          // use the value for isAdmin
          if (isAdmin == true) {
            return Container();
          } else {
            return Container();
          }
        } else if (snapshot.hasError) {
          //handle your error
          return Container();
        } else {
          // handle your loading
          return CircularProgressIndicator();
        }
      },
    ),
    

    【讨论】:

    • 你能给我举个例子吗?我尝试了很多使用这两个,但它对我不起作用
    • 我更新了答案以包含一个代码示例。
    • 谢谢你,这帮助很大。 (虽然我没有做“Globals.isAdmin”
    【解决方案2】:

    尝试用下一个方法改变你的 _checkRole() 方法:

    Future<bool> _checkRole() async {
      var firebaseUser = FirebaseAuth.instance.currentUser;
      return await FirebaseFirestore.instance
        .collection("users")
        .doc(firebaseUser.uid)
        .get()
        // we create the new Future with bool value, depending on 
        // the Firebase response and throw it away as a result of
        // the _checkRole method
        .then((value) => Future.value(value.data()['role']) == 'admin'));
    }
    

    然后在您的组件中使用FutureBuilder。所以你的布局应该是这样的:

    child: FutureBuilder<bool>(
      future: _checkRole,
      builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
        if (snapshot.hasData) { // check whether we have any data in our Future object
          final isAdmin = snapshot.data; // bool type
          return isAdmin
              ? buildListTile(
                  'Admin Panel', Icons.admin_panel_settings_sharp, () {
                  Navigator.of(context).pushNamed(AdminScreen.routeName);
                })
              : buildListTile('User dashboard', Icons.person, () {}),
        }
        
        // if snapshot doesn't have data return a widget with an error message
        return Center(
          child: Text('Error!'),
        );
      },
    ),
    

    【讨论】:

    • 我尝试了这种方法,并尝试打印 snapshot.dataisAdmin 并且它会显示真实,我已与管理员连接,但它仍然会返回中心小部件
    • print(snapshot.data) 显示什么?
    • 它打印正确的布尔值,解决方案有效,但需要返回,所以buildListTile() 后面必须有一个return
    【解决方案3】:

    为 isAdmin 变量设置一个默认值

    bool isAdmin = false;
    

    或者如果你有一个成员模型,我的意思是你创建了一个名为 Member 的类

    class Member {
      // create a method for deteriming if the the member is an admin or not
      bool isAdmin() async {
        var firebaseUser = FirebaseAuth.instance.currentUser;
        await FirebaseFirestore.instance
        .collection("users")
        .doc(firebaseUser.uid)
        .get()
        .then((value) {
          return ((value.data()['role']) == 'admin');
        });
      }
    }
    

    现在,您可以使用此方法检查该成员是否为管理员

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多