Flutter how to get data from async function
You should first understand what is Future
operations (Future
function in your case). Future operations are the operations which take time to perform and return the result later. To handle this problem, we use Asynchronous functions.
Asynchronous Function let your program continue other operations while the current operation is being performed. Dart uses Future
objects (Futures) to represent the results of asynchronous operations. To handle these operations, we can use async/await, but it is not possible to integrate async and await on widgets. So it is quite tricky to handle futures in widgets. To solve this problem flutter provided a widget called FutureBuilder
.
In FutureBuilder
, it calls the Future function to wait for the result, and as soon as it produces the result it calls the builder function where we build the widget.
Here is how it should be:
class Home extends StatefulWidget { @override _HomeState createState() => _HomeState();}class _HomeState extends State<Home> { List allItems = new List(); Future<List> pegaDados() async{ var items = await geraCardapio(); // TODO: Add this function to this class for (var i = 0; i < items.length; i++) { print((items[i].toMap())); allItems.add(items[i].toMap()); } return items; } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: Text('Demo')), body: FutureBuilder( future: pegaDados(), builder: (context, snapshot){ if(snapshot.connectionState == ConnectionState.done){ return Container( child: ListView.builder( itemCount: snapshot.data.length, itemBuilder: (context, index) { return ListTile( leading: Image.asset("assets/"+ snapshot.data[index]['imagem'], fit: BoxFit.contain,), title: Text(snapshot.data[index]['pedido']), trailing: Text(snapshot.data[index]['valor']), ); }, ), ); } else if(snapshot.hasError){ throw snapshot.error; } else{ return Center(child: CircularProgressIndicator()); } }, ), ); }}
Here is the link to a short video that will explain FutureBuilder
in a concise way.
I'm not sure how your widget tree looks like, but I'm assuming ListView
is being built simultaneously with pegaDados
. What you're looking for is a FutureBuilder
:
Future<dynamic> pegaDados() async{ var items = await geraCardapio(); return items.map((item) => item.toMap());}...FutureBuilder<dynamic>( future: pegaDados(), builder: (BuilderContext context, AsyncSnapshot snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return Text('Uninitialized'); case ConnectionState.active: case ConnectionState.waiting: return Text('Awaiting result...'); case ConnectionState.done: if (snapshot.hasError) throw snapshot.error; // // Place here your ListView. // } return null; // unreachable }