在空安全后,参数类型“Function”无法分配给参数类型“void Function()?”

171

我想制作一个抽屉,上面有不同的项目,所以我正在为DrawerItems创建一个单独的文件,并使用构造函数将数据传递到主文件。但是在onPressed函数中,我遇到了以下错误:

"The argument type 'Function' can't be assigned to the parameter type 'void Function()'"

class DrawerItem extends StatelessWidget {
    
      final String text;
      final Function onPressed;
    
      const DrawerItem({Key key, this.text, this.onPressed}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return FlatButton(
          child: Text(
            text,
            style: TextStyle(
              fontWeight: FontWeight.w600,
              fontSize: 18.0,
            ),
          ),
          onPressed: onPressed,
        );
      }
    }

有人知道为什么吗?

20个回答

378

将您的代码更改为接受VoidCallback而不是Function作为onPressed
顺便说一下,VoidCallback只是void Function()的简写,因此您也可以将其定义为final void Function() onPressed;

更新后的代码:

class DrawerItem extends StatelessWidget {
    
      final String text;
      final VoidCallback onPressed;
    
      const DrawerItem({Key key, this.text, this.onPressed}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return FlatButton(
          child: Text(
            text,
            style: TextStyle(
              fontWeight: FontWeight.w600,
              fontSize: 18.0,
            ),
          ),
          onPressed: onPressed,
        );
      }
    }

2
如果我想在函数中使用参数,有没有解决方案?例如TextField函数中的“onSubmitted”,因为它会给我报错:“无法将参数类型'void Function()?'分配给参数类型'void Function(String)?”。这个错误有什么解决方案吗? - Hitesh Danidhariya
2
@HiteshDanidhariya 是的,你可以简单地将它添加到括号中,即 void Function(String myString) - Pieter van Loon

131

Dart 2.12(空值安全):

不再使用

final Function? onPressed; // Bad
使用
final void Function()? onPressed; // Good
final VoidCallback? onPressed; // Good

2
最终的 Function()? onPressed; 对我有用,谢谢 :) - Askani
4
一个“Function”可以是任何东西,比如“Function()”,“Function(int)”等等,这就是为什么在Dart空安全中,你应该明确告诉这个“Function”是什么。 - CopsOnRoad
@CopsOnRoad 感谢您的观点。但是我想知道,正如您所说的Function()和Function(int),我认为这是一种多态性,而不是真正的空安全 :D - vietstone
2
@vietstone 多态是一件不同的事情。Function onPressed 可以通过 onPressed(), onPressed(1), onPressed(1, true) 调用,因此你可能会遇到运行时错误,但是 Function() onPressed 只能通过 onPressed() 调用。这件事与空安全无关,而是与 Dart 2.12 相关。 - CopsOnRoad
简短且有效的答案...谢谢 :) - sina
显示剩余2条评论

17

那是因为FlatButton内的onPressed不是普通函数,而是VoidCallBack函数。 您可以尝试这样做:

final VoidCallBack onPressed;

当你将一个普通的function传递给VoidCallBack时,请参考官方文档这里

enter image description here

更新后的代码:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  _myFunction() => print("Being pressed!");

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            DrawerItem(
              text: "Hello Jee",
              onPressed: _myFunction,
            ),
          ],
        ),
      ),
    );
  }
}

class DrawerItem extends StatelessWidget {
  final String text;
  final Function onPressed;

  const DrawerItem({Key key, this.text, this.onPressed}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      child: Text(
        text,
        style: TextStyle(
          fontWeight: FontWeight.w600,
          fontSize: 18.0,
        ),
      ),
      onPressed: onPressed,
    );
  }
}

不,问题不在于仍然使用final VoidCallBack onPressed; 但还是谢谢你。 - dosytres
你的代码对我来说运行良好,你的Flutter版本是多少?或者你能向我展示你将哪个“函数”作为参数传递给了“DrawerItem”吗? - Hamza
我的Flutter版本是1.22.o,我知道它很老了,但是我必须使用这个版本,因为我在Java方面遇到了一个错误,而且它无法在更新的版本上运行。 - dosytres
实际上你的代码在这里没问题,你能告诉我你正在将哪种类型的“函数”作为参数传递吗? - Hamza
这是完整的代码,然后我想能够通过构造函数将其传递到另一个文件中。 - dosytres
不是VoidCallBack,而是VoidCallback。'b'是小写的。 - Reinier Garcia

8

取代

final Function? onPressed; 

final Function()? onPressed; // add parenthesis in Function

7
在定义函数时,需要在关键字 Function 后面加上圆括号 ()
import 'package:flutter/material.dart';

class Answer extends StatelessWidget {
  final Function() onPressed; //parenthesis () on function
  final String name;
  const Answer(this.name, this.functionMessage, {Key? key}) : super(key: 
key);

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: const EdgeInsets.only(top: 10),
        width: double.infinity,
        child: ElevatedButton(
           style: ElevatedButton.styleFrom(
           primary: Colors.black, // background
           onPrimary: Colors.white, // foreground
          ),
          onPressed: onPressed,
          child: Text(name),
        ));
  }
}

6

如果您了解Dart的数据类型和null安全,这个问题有两种可能的解决方案。

第一种:

添加类型VoidCallback?

class DrawerItem extends StatelessWidget {
      final String text;
      final VoidCallback? onPressed;
    
      const DrawerItem({Key key, this.text, this.onPressed}) : super(key: key); }

第二点:

如果你是初学者,在数据类型方面不太了解,你可以使用动态类型,让Dart编译器为你处理类型。

class DrawerItem extends StatelessWidget {
          final String text;
          final dynamic onPressed;
    
      const DrawerItem({Key key, this.text, this.onPressed}) : super(key: key); }

3

使用:

VoidCallback? _onPressed

改为:

VoidCallback _onPressed

这对我很有帮助!


3

使用

onPressed: () => delete(),

替代

onPressed:delete,

3
如果您在修改onPressed函数后仍然遇到错误"The parameter onPressed can't have a value of null because of its type, but the implicit default value is null.",只需应用空安全性即可解决问题,操作如下:
final VoidCallback? onPressed;

这个可以在 Dart 2.x 中使用。


2

您可以使用void Function而不是Function,您可以像这样指定函数的类型:

void Function(bool) onPressed;

 


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接