How to fix error: type 'Null' is not a subtype of type '() => void'

How to fix error: type 'Null' is not a subtype of type '() => void'

我有一个管理员登录页面,管理员可以在其中添加 ID 和密码以访问管理区域。 Firebase 数据库中有一个管理集合,用于存储 ID 和密码。管理员集合与用户登录页面分开,并与在允许访问之前使用 Firebase 身份验证的用户集合分开。用户访问继续正常工作。当我在管理员登录屏幕上填写两个输入框并单击按钮以获取访问权限时,出现错误对话框消息,指示两个输入字段中没有任何数据,即使有数据也是如此。如果我不对代码执行任何操作,然后热重载并再次单击按钮,我可以访问管理员,但我在控制台中收到以下错误消息。

构建 ShoppingAdminSignInPage 时抛出了以下 _TypeError(脏,依赖项:[_LocalizationsScope-[GlobalKey#2c797]],状态:_ShoppingAdminSignInPageState#e3b3d): 类型 'Null' 不是类型 '() => void'

的子类型

我的代码中显然写错了一些东西。错误似乎出在 ShoppingAdminSignInButton 中。预先感谢您的帮助。

class ShoppingAdminSignInPage extends StatefulWidget {
  const ShoppingAdminSignInPage({Key? key}) : super(key: key);

  @override
  State<ShoppingAdminSignInPage> createState() =>
      _ShoppingAdminSignInPageState();
}

class _ShoppingAdminSignInPageState extends State<ShoppingAdminSignInPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final TextEditingController _adminIDController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return AdaptiveLayoutScaffold(
      appBar: const ShoppingAdminSignInPageAppBar(),
      landscapeBodyWidget: Container(),
      portraitBodyWidget: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: Column(
            mainAxisSize: MainAxisSize.max,
            children: [
              const ShoppingAdminSignInHeader(),
              Form(
                key: _formKey,
                child: Column(
                  children: [
                    const SizedBox(
                      height: 50.0,
                    ),
                    AdminSignInTextField(
                      controller: _adminIDController,
                      labelText: TextFieldLabel.adminID,
                      prefixIcon: Icons.person,
                      textInputAction: TextInputAction.next,
                    ),
                    AdminSignInTextField(
                      controller: _passwordController,
                      labelText: TextFieldLabel.password,
                      prefixIcon: Icons.password,
                      textInputAction: TextInputAction.done,
                    ),
                    ShoppingAdminSignInButton(
                      onPressed: _adminIDController.text.isNotEmpty &&
                              _passwordController.text.isNotEmpty
                          ? logInAdmin()
                          : () => showDialog(
                              context: context,
                              builder: (ctx) {
                                return const ErrorAlertDialog(
                                  message: DialogString.addAdminIDAndPassword,
                                );
                              }),
                    ),
                    const NotAnAdminButton(),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  logInAdmin() {
    FirebaseFirestore.instance.collection('admins').get().then((snapshot) {
      snapshot.docs.forEach((result) {
        if (result.data()['id'] != _adminIDController.text.trim()) {
          SnackBarUtil.showSnackBar(
            context,
            SnackBarString.idNotCorrect,
          );
        } else if (result.data()['password'] !=
            _passwordController.text.trim()) {
          SnackBarUtil.showSnackBar(
            context,
            SnackBarString.passwordNotCorrect,
          );
        } else {
          SnackBarUtil.showSnackBar(
            context,
            'Welcome ${result.data()['name']}',
          );
          setState(() {
            _adminIDController.text = '';
            _passwordController.text = '';
          });
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => const UploadItemsPage(),
            ),
          );
        }
      });
    });
  }
}
onPressed: _adminIDController.text.isNotEmpty && _passwordController.text.isNotEmpty
  ? logInAdmin()
  : () => showDialog(

上面,你说的是如果条件为真(在这种情况下条件是 _adminIDController_passwordController 都不是空的)那么它应该 运行 logInAdmin 并等待它完成,然后 运行 无论什么 logInAdmin returned.

Dart 认为 logInAdmin 将 return 一个函数,它应该 运行 该函数。这个不行,你要按钮直接运行logInAdmin.

要解决此问题,请删除括号:

onPressed: _adminIDController.text.isNotEmpty && _passwordController.text.isNotEmpty
  ? logInAdmin
  : () => showDialog(

这样,您不是在分配函数的结果,而是在分配函数本身。

此外,作为一般性建议,您应该始终在您的函数中声明一个 return 类型,以便 dart 可以在发生这种情况时告诉您

void logInAdmin() {
  ...