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

FlutterDartDart Null-Safety

Flutter 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

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

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;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondosytresView Question on Stackoverflow
Solution 1 - FlutterPieter van LoonView Answer on Stackoverflow
Solution 2 - FlutterCopsOnRoadView Answer on Stackoverflow
Solution 3 - FlutterHamzaView Answer on Stackoverflow
Solution 4 - FlutterAssemView Answer on Stackoverflow
Solution 5 - FlutterJohnView Answer on Stackoverflow
Solution 6 - FlutterTrịnh Đức DuyView Answer on Stackoverflow
Solution 7 - Flutteroeng hoklengView Answer on Stackoverflow
Solution 8 - FlutterMarkDionee BView Answer on Stackoverflow
Solution 9 - FlutterMUHAMMAD SHAHID RAFI C PView Answer on Stackoverflow
Solution 10 - FlutterHemantPra389View Answer on Stackoverflow
Solution 11 - Flutteryara.devView Answer on Stackoverflow