The argument type 'Function' can't be assigned to the parameter type 'void Function()?' after null safety
FlutterDartDart Null-SafetyFlutter Problem Overview
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?
Flutter Solutions
Solution 1 - Flutter
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,
);
}
}
Solution 2 - Flutter
Dart 2.12 (Null safety):
Instead of
final Function? onPressed; // Bad
use
final void Function()? onPressed; // Good
final VoidCallback? onPressed; // Good
Solution 3 - Flutter
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
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,
);
}
}
Solution 4 - Flutter
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),
));
}
}
Solution 5 - Flutter
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
Solution 6 - Flutter
use:
VoidCallback? _onPressed
instead of:
VoidCallback _onPressed
it's work for me!
Solution 7 - Flutter
You can use void Function instead of Function and you can specify you type of your function like this:
void Function(bool) onPressed;
Solution 8 - Flutter
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 */
],
),
));
}
Solution 9 - Flutter
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
Solution 10 - Flutter
use:
dynamic onPressed;
or
onPressed;
it will autodetect or set the parameter type as dynamic
instead of:
VoidCallback onPressed;
Solution 11 - Flutter
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;