Home > Back-end >  Flutter how to pass async function to another widget?
Flutter how to pass async function to another widget?

Time:05-12

I am new to flutter and I am running into a bit of trouble. I have a stateful widget class where I generate a list of stateless widgets and pass an async function to the stateless widget. The problem is that the function is being called while being passed (check comments in code). What is the correct way to pass the function and call it from another widget?

Note: I do not want to declare the function in the stateless widget as I want to setState() after the api call (completeTask).

Here is my stateful widget code :

    void getData() async {
      //...api call to get data
      final routesList = List<Widget>.generate(
        jsonResponse['id'].length, (i) =>TaskCard(
        completeTask: completeTask(int.parse(jsonResponse['id'][i])), //function executed here
        )
       );
       //...
    }
    
     completeTask(int id) async{
         //... API call
         setState(() {
             //...
            });
     }
}

My stateless widget looks like this:

class TaskCard extends StatelessWidget {
    TaskCard({Key key, this.id,this.completeTask}) : super(key: key);

      Future<void> completeTask;

        //...
        IconButton(
        icon: Icon(Icons.done,color: Colors.green,),
        onPressed: () => completeTask,
        )
        //...
    }

CodePudding user response:

I figured it out. Below is the correct code:

void getData() async {
      //...api call to get data
      final routesList = List<Widget>.generate(
        jsonResponse['id'].length, (i) =>TaskCard(
        completeTask: () {
                setState(() {
                  completeTask(int.parse(jsonResponse['id'][i]));
                },
                );
              }
                )
        );
       //...
    }

This is the other widget

IconButton(
       icon: Icon(Icons.done,color: Colors.green,),
       onPressed: completeTask,
)

CodePudding user response:

To avoid completeTask from being called immediately in the Stateful widget, use () => ... when giving it to the Stateless widget.

So we could have the following in the Stateful widget:

  void getData() async {
    final routesList = List<Widget>.generate(
      jsonResponse['id'].length, (i) => TaskCard(
        // so this is the call we should wrap, if we don't do it this way
        // we will be calling it directly when the widget is being created
        completeTask: () async => completeTask(int.parse(jsonResponse['id'][i])),
      )
    );
    //...
  }

Then in the Stateless widget, you need to improve the type of completeTask. It is Future<void> Function() and not just Future<void>

class TaskCard extends StatelessWidget {
  TaskCard({Key key, this.id, this.completeTask}) : super(key: key);

  Future<void> Function() completeTask;

    //...
    IconButton(
      icon: Icon(Icons.done, color: Colors.green),
      // remember to call the passed function here, notice the ()
      onPressed: () => completeTask(),
    )
    //...
 
  • Related