Search code examples
flutterlistviewcheckbox

The argument type 'void Function(bool?, int) Function(bool?, dynamic)' can't be assigned to the parameter type 'dynamic Function(bool?)?'


I'm trying to learn Flutter and I'm developing Todo app But I got stuck with a bug Here is my code

List view

body: ListView.builder(
          itemCount: todos.length,
          itemBuilder: (context, index) {
            return Todo(
                taskName: todos[index][0],
                completed: todos[index][1],
                onChanged: (value, index) => checkboxChanged); // here the index argument is causing the error
          },
        )

and the Todo class


class Todo extends StatelessWidget {
  final String taskName;
  final bool completed;

  Function(bool?)? onChanged; // the method 

  Todo(
      {super.key,
      required this.taskName,
      required this.completed,
      required this.onChanged});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(left: 10, top: 10, right: 10),
      child: Container(
          padding: EdgeInsets.all(20),
          decoration: BoxDecoration(
              color: Colors.yellow, borderRadius: BorderRadius.circular(10)),
          child: Row(
            children: [
              Checkbox(
                value: completed,
                onChanged: onChanged,
                activeColor: Colors.black,
              ),
              Text(taskName),
            ],
          )),
    );
  }
}

There comes up when I add the index parameter here

  void checkboxChanged(bool? value, int index) { // if I remove the indext parameter from here and from the Todo instantiation in the ListView the error will be gone. but I need that way
    setState(() {
      todos[index][1] = !todos[index][1];
    });
  }

The error message I'm facing is

The argument type 'void Function(bool?, int) Function(bool?, dynamic)' can't be assigned to the parameter type 'dynamic Function(bool?)?'

Any help is appreciated. Thanks...


Solution

  • The field onChanged of your widget-class Todo is defined as:

    Function(bool?)? onChanged
    
    • Function indicates the field onChanged is a function. In Dart everything is an object, event functions.
    • The ? at the end indicates the field can be null
    • Since the return type of the function is omitted it has the implicit return of "void".
    • (bool?) indicates this function takes one argument which is a boolean or null.

    However in your constructor of the instance of Todo in the ListView you are passing (value, index) => checkboxChanged which is a function that takes two arguments, 1) value and 2) index, and returns another function checkboxChanged (again, since everything is an object you can return a function as the result from another function).

    To fix this you shall comply to what Todo is expected in the argument onChanged:

    body: ListView.builder(
              itemCount: todos.length,
              itemBuilder: (context, index) {
                return Todo(
                    taskName: todos[index][0],
                    completed: todos[index][1],
                    onChanged: (value) => checkboxChanged(value, index),
                 );
              },
            )
    

    This is equivalent to passing to onChanged an unnamed function which takes the "value" object and within that function it calls checkboxChanged with that value and the index provided by the builder of ListView.

    onChanged: (value) {
      checkboxChanged(value, index);
    }