How can you call a void function in Flutter without passing a parameter?

7.8k Views Asked by At

I'm new to Flutter and am working through the intro course on Udacity. In one of the tasks, I was trying to follow the code and I can't make much sense of it. Here's the code from the solution of the project (I've cut and paste the parts that matter, and also legal disclaimer I do not own any of this code, it's from the sample Flutter Udacity project):

Widget build(BuildContext context) {
    final input = Padding(
      padding: _padding,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [

          TextField(...),

          _createDropdown(_fromValue.name, _updateFromConversion),
        ],
      ),
    );
}

void _updateFromConversion(dynamic unitName) {
    setState(() {
      _fromValue = _getUnit(unitName);
    });
    if (_inputValue != null) {
      _updateConversion();
    }
  }

Widget _createDropdown(String currentValue, ValueChanged<dynamic> onChanged) {
    return Container(
      margin: EdgeInsets.only(top: 16.0),
      decoration: BoxDecoration(...),

      padding: EdgeInsets.symmetric(vertical: 8.0),
      child: Theme(...),

        child: DropdownButtonHideUnderline(
          child: ButtonTheme(
            alignedDropdown: true,
            child: DropdownButton(
              value: currentValue,
              items: _unitMenuItems,
              onChanged: onChanged,
              style: Theme.of(context).textTheme.title,
            ),
          ),
        ),
      ),
    );
}

Here's where I'm stuck. _updateFromConversion requires an input parameter unitName. But when they call it, in _createDropdown, they don't pass any. So how does _updateFromConversion know what unitName is? Also, is _updateFromConversion executed before _createDropdown, or is it executed when the "onChanged" property of DropdownButton is set?

Second question: they're passing that function with return type void into _createDropdown, which is expecting ValueChanged. Shouldn't this throw an error?

If someone can explain the flow of this code and what I am missing I would greatly appreciate it. Thank you!

2

There are 2 best solutions below

3
Renato On BEST ANSWER

You seem to be misunderstanding the assignment of a variable to a function for a function call.

Let me try to show it with example code.

void _updateFromConversion(dynamic unitName) {
    print("Unit name: $unitName");
}

class SomeClass {
    void Function(dynamic arg) myFunction;
}

void main() {
    final c = SomeClass()..myFunction = _updateFromConversion;
    print("Created c. Calling its function");
    c.myFunction("foo");
    print("Done");
}

When you run this code, you will see this printed:

Created c. Calling its function
Unit name: foo
Done

This shows that the _updateFromConversion function is not called when you create the SomeClass instance in SomeClass()..myFunction = _updateFromConversion;. This is only an assignment (it assigns to the field myFunction the value _updateFromConversion... yes, in Dart a function itself can be a value)!

You should know that because there's no () after the function name, and function invocation in Dart always must contain the list of arguments between () even if it's empty.

So, here's where the function is invoked:

c.myFunction("foo");

See? There's a list of arguments containing a single value, "foo". That's why the function then prints Unit name: foo, because the argument unitName takes the value "foo".

TL;DR

This is a function invocation:

c.myFunction("foo");

This is NOT:

c.myFunction;
0
Alex Radzishevsky On

Yashvin,

In dart function can be passed as parameter to other functions. This is usually used to pass callbacks for instance.

In example you provided, function _updateFromConversion is passed as parameter onChanged to another function _createDropdown.

In that function it will be assigned to onChanged listener of DropdownButton button.

Every time value of DropdownButton changes, this function will be invoked and will be passed selected value of DropdownButton.