Флаттер, как получить данные из асинхронной функции - PullRequest
3 голосов
/ 06 ноября 2019

У меня очень большие трудности с этим. Я вызываю асинхронную функцию, которая будет получать некоторую информацию из SQLite, но я не могу ее получить. Он просто отображает пустой экран, на котором должен быть вид списка.

List allItems = new List();


Future<void> pegaDados() async{
  var itens = await geraCardapio();

  for (var i = 0; i < itens.length; i++) {
    print((itens[i].toMap()));
    allItems.add(itens[i].toMap());
  }

}

print(pegaDados());


  return ListView.builder(
    itemCount: allItems.length,
    itemBuilder: (context, index) {
      return ListTile(
        leading: Image.asset("assets/"+ allItems[index]['imagem'], fit: BoxFit.contain,),
        title: Text(allItems[index]['pedido']),
        trailing: Text(allItems[index]['valor']),
      );
    },
  );

Большое спасибо.

Мне удалось найти решение, благодаря обоим людям, которые ответили на вопрос (используяоба решения мне удалось получить этого маленького франкенштейна)

    Future<dynamic> pegaDados() async{
  var allItems = await geraCardapio();

  return allItems.map((allItems) => allItems.toMap());
}



return FutureBuilder(
      future: pegaDados(),
      builder: (context, snapshot){
        if(snapshot.connectionState == ConnectionState.done){
          print(snapshot.data);
          var objeto = [];

          for (var i in snapshot.data) {
            objeto.add(i);
          }

          print(objeto);
          return Container(
              child: ListView.builder(
            itemCount: objeto.length,
            itemBuilder: (context, index) {
              return ListTile(
                leading: Image.asset("assets/"+ objeto[index]['imagem'], fit: BoxFit.contain,),
                title: Text(objeto[index]['pedido']),
                trailing: Text(objeto[index]['valor'].toString()),
              );
            },
              ),
          );
        }
        else if(snapshot.hasError){
          throw snapshot.error;
        }
        else{
          return Center(child: CircularProgressIndicator());
        }
      },
    );

благодаря Мохаммеду Ассему Насеру и Элии Коэну за помощь!

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Сначала вы должны понять, что такое Future операции (Future функция в вашем случае). Будущие операции - это операции, которые требуют времени для выполнения и возвращают результат позже. Чтобы решить эту проблему, мы используем Асинхронные функции .

Асинхронные функции позволяют вашей программе продолжать другие операции во время выполнения текущей операции. Dart использует Future объекты (Futures) для представления результатов асинхронных операций. Для обработки этих операций мы можем использовать async / await , но невозможно интегрировать async и await в виджеты. Так что обрабатывать фьючерсы в виджетах довольно сложно. Чтобы решить эту проблему, флаттер предоставил виджет с именем FutureBuilder.

В FutureBuilder он вызывает функцию Future , чтобы дождаться результата, и как только он выдаст результат, онвызывает функцию builder , где мы создаем виджет.

Вот как это должно быть:

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

Вот ссылка накороткое видео, которое кратко объяснит FutureBuilder.

2 голосов
/ 06 ноября 2019

Я не уверен, как выглядит ваше дерево виджетов, но я предполагаю, что ListView создается одновременно с pegaDados. То, что вы ищете, это 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
  }
...