参数类型“Function”不能分配给参数类型“void Function()?”在零安全之后

Posted

技术标签:

【中文标题】参数类型“Function”不能分配给参数类型“void Function()?”在零安全之后【英文标题】:The argument type 'Function' can't be assigned to the parameter type 'void Function()?' after null safety 【发布时间】:2021-02-05 13:56:24 【问题描述】:

我想实现制作一个带有不同项目的抽屉,所以我为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,
        );
      
    

有人知道为什么吗?

【问题讨论】:

【参考方案1】:

那是因为onPressed 里面的FlatButton 不是一个正常的函数它的VoidCallBack 函数。 你可以试试这样:

final VoidCallBack onPressed;

同时,您将普通的function 传递给VoidCallBack

关注官方文档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;不过谢谢。 您的代码对我来说运行良好,您的 Flutter 版本是多少?或者你能告诉我你将哪个function作为参数传递给DrawerItem 我的 Flutter 版本是 1.22.o,我知道它是旧版本,但我必须使用这个版本,因为我在使用 java 时出现错误,并且它不适用于更新版本。 其实你的代码在这里没问题,你能告诉我你作为参数传递的function的类型吗? 这是完整的代码,然后我希望能够通过构造函数将它传递给另一个文件【参考方案2】:

更改您的代码以接受VoidCallback 而不是FunctiononPressed。 顺便说一句,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,
        );
      
    

【讨论】:

如果我想要一个带有参数的函数,有什么解决方案吗?例如文本字段函数“onSubmitted”,因为它给我的错误是“参数类型'void Function()?'不能赋值给参数类型'void Function(String)?"。这个错误有什么解决办法吗? @HiteshDanidhariya 是的,您可以简单地将其添加到括号中,即void Function(String myString)【参考方案3】:

如果您仍然收到此错误“参数onPressed 的值不能为null,因为它的类型,但隐式默认值为null。”修改onPressed函数后,只需应用空安全来解决这样的问题;

final VoidCallback? onPressed;

这适用于Dart 2.x

【讨论】:

【参考方案4】:

Dart 2.12(零安全):

代替

final Function? onPressed; // Bad

使用

final void Function()? onPressed; // Good
final VoidCallback? onPressed; // Good

【讨论】:

最终函数()?按下;为我工作,谢谢:) 你能解释一下它背后的逻辑吗?或者给我一些关于这个的链接?谢谢。 @vietstone A Function 可以是任何东西,例如 Function()Function(int) 等,这就是为什么使用 Dart 空安全性,您应该明确告诉 Function 是什么。跨度> @CopsOnRoad 谢谢你的意见。但我想知道,正如您所说的 Function() 和 Function(int),我认为这是一种多态性,而不是真正的 Null 安全性:D @vietstone 多态性是另一回事。 Function onPressed 可以被onPressed()onPressed(1)onPressed(1, true) 调用,所以你可能会遇到运行时错误,但Function() onPressed 只能被onPressed() 调用。这件事与 null 安全性无关,但与 Dart 2.12 无关。【参考方案5】:

使用:

VoidCallback? _onPressed

代替:

VoidCallback _onPressed

这对我有用!

【讨论】:

【参考方案6】:

如果您在调用DrawerItem 时发送参数,您还应该像这样向Function 添加一个参数? final void Function(new par) onPressed;

【讨论】:

【参考方案7】:

2021:如果您的构造函数接受多个参数,您可能希望使用命名参数以避免混淆:

示例:应答按钮小部件

class AnswerButton extends StatelessWidget 
    
      late final Function()? submitAnswer;
    
      Answer(injectMethod) 
        this.selectHandler = submitAnswer;
      
    

主要

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text("App Title"),
      ),
      body: Column(
        children: [
          AnswerButton(injectMethod: _nextQuestion) /* <--- named argument */
        ],
      ),
    ));
  

【讨论】:

【参考方案8】:

您可以使用 void Function 代替 Function,您可以像这样指定您的函数类型:

void Function(bool) onPressed;

 

【讨论】:

【参考方案9】:

定义函数时,在关键字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),
        ));
  

【讨论】:

【参考方案10】:

如果以上解决方案都检查了,那么参考下面的代码

class ManageMenu extends StatelessWidget 
  const ManageMenu(
      Key? key,
      required this.faIcon,
      required this.text,
      required this.onTapFunction)
      : super(key: key);

  final FaIcon faIcon;
  final String text;
  final Function onTapFunction;

  @override
  Widget build(BuildContext context) 
    return GestureDetector(
      onTap: () => onTapFunction,
      child: ListTile(
        leading: faIcon,
        title: Text(text),
      ),
    );
  

您可能将错误的语法写成onTap:onTapFunction 而不是onTap: () =&gt; onTapFunction

【讨论】:

【参考方案11】:

使用:

dynamic onPressed;

onPressed; 会自动检测或设置参数类型为动态

代替:

VoidCallback onPressed;

【讨论】:

以上是关于参数类型“Function”不能分配给参数类型“void Function()?”在零安全之后的主要内容,如果未能解决你的问题,请参考以下文章

参数类型“Function”不能分配给参数类型“void Function()?”在零安全之后

参数类型“Widget Function(Categoria)”不能分配给参数类型“dynamic Function(Child)”。 (型号)颤振

Flutter中的参数类型'Widget Function(BuildContext)'不能分配给参数类型'Widget Function(BuildContext,Widget)'错误

参数类型“字符串”不能分配给参数类型“对象?函数(对象?,对象?)?

参数类型 'List<Todo>? Function(QuerySnapshot<Object?>)' 不能分配给参数类型 'List<Todo> Function

参数类型“Map<String, dynamic> Function()”不能分配给参数类型“Map<String, dynamic>”