The argument type 'Function' can't be assigned to the parameter type 'void Function()?' after null safety

186.8k views Asked by At

I want to achieve to make a drawer with different items on it, so I am creating a separate file for the DrawerItems and the with the constructor, pass the data to the main file. But I get the following error on the onPressed function:

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

Anyone knows why?

20

There are 20 answers

2
Pieter van Loon On BEST ANSWER

Change your code to accept a VoidCallback instead of Function for the onPressed.
By the way VoidCallback is just shorthand for void Function() so you could also define it as final void Function() onPressed;

Updated code:

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,
        );
      }
    }
6
Hamza On

Well that's because onPressed inside FlatButton is not a normal function its VoidCallBack Function. You can try something like this:

final VoidCallBack onPressed;

While, you are passing a normal function into a VoidCallBack

Follow the official doc here

enter image description here

Updated Code:

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,
    );
  }
}
0
John On

If you still get this error "The parameter onPressed can't have a value of null because of its type, but the implicit default value is null." after modifying the onPressed function, just apply the null safety to fix the problem like this;

final VoidCallback? onPressed;

This works with Dart 2.x

7
CopsOnRoad On

Dart 2.12 (Null safety):

Instead of

final Function? onPressed; // Bad

use

final void Function()? onPressed; // Good
final VoidCallback? onPressed; // Good
0
احمد طارق النونو On

use

onPressed: () => delete(),

instead of

onPressed:delete,
0
Assem On

Put the parentheses () after the keyword Function when defining the 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),
        ));
  }
}
0
oeng hokleng On

You can use void Function instead of Function and you can specify you type of your function like this:

void Function(bool) onPressed;

 

0
Trịnh Đức Duy On

use:

VoidCallback? _onPressed

instead of:

VoidCallback _onPressed

it's work for me!

0
joemdjossou On

The Dart Sound null safety (sdk: '>=3.0.5 <4.0.0') will make you use:

final Function()? onPressed; //make use of parenthesis

instead of: final Function? onPressed; or: final void Function? onPressed;

0
MUHAMMAD SHAHID RAFI C P On

If all above solution checked, then refer below code

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

You may wrote wrong syntax as onTap:onTapFunction instead of onTap: () => onTapFunction

0
yara.dev On

if you are sending the parameter while calling the DrawerItem you should also add a parameter to Function like that final void Function(new par) onPressed;

0
Mark Dionnie On

2021: If you have a constructor accepting multiple parameters, you might want to use named arguments to avoid confusion:

Sample: Answer Button Widget

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

Main

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

use:

dynamic onPressed;

or

onPressed; it will autodetect or set the parameter type as dynamic

instead of:

VoidCallback onPressed;

0
Shivam Tiwari On

Instead of

final Function? onPressed; 
Use
final Function()? onPressed; // add parenthesis in Function
1
Swaraj Kumar On

Change your code to accept a VoidCallback instead of Function for the onPressed. By the way VoidCallback is just shorthand for void Function() so you could also define it as final void Function() onPressed;

0
Mohammed Salim Al-Othman On
class TaskCheckBox extends StatelessWidget {
  final bool checkBoxState;
  **final void Function(bool? a)? onChecked**;

  const TaskCheckBox(
    this.checkBoxState,
    this.onChecked, {
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Checkbox(
        activeColor: Colors.lightBlueAccent,
        value: checkBoxState,
        onChanged: **onChecked**);
  }
}
0
Mashood .H On

There are 2 possible solutions for this if you aware of data types in dart and null safety

1st:

add type VoidCallback?

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

2nd:

if you are a beginner and don't know much about data type you can use dynamic and let dart compiler handled type for you.

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

For any onTap, onPressed, onChange, etc. functions which returns void Function()?

Always use () => or () {} and then declare your function/functions...

For example:

@override
Widget build(BuildContext context) {
  return ElevatedButton(
    child: Text(text),
    onPressed: () => anyFunctionCall(), // ONLY SINGLE FUNCTION CAN BE CALLED
  );
}

OR

@override
Widget build(BuildContext context) {
  return ElevatedButton(
    child: Text(text),
    onPressed: () {
      firstFunctionCall(),
      secondFunctionCall(),
      // ... MULTIPLE FUNCTIONS CAN BE CALLED
    }
  );
}
0
Musfiq Shanta On

void Function(bool? a)? callback;

Check the screenshot of how void callback bool function work enter image description here

0
MD ALI On

use this :

final void Function()? onTapping;

or

final voidCallback? onPressed;