Флаттер - Возможно ли извлечь данные из будущего без использования FutureBuilder? - PullRequest
0 голосов
/ 11 мая 2018

Я читаю вводимые пользователем данные (в данном случае почтовый индекс) из TextField, которые мне нужно проверить на предмет достоверности в базе данных.Однако мне нужно сделать асинхронный запрос к базе данных внутри кнопки отправки (RaisedButton в данном случае) onPressed: () {} лямбда-функции.В большинстве языков программирования это довольно простая и простая задача.Однако проблема, с которой я сталкиваюсь во Flutter, заключается в том, что Future объекты, возвращаемые из асинхронных запросов к базе данных, могут потребляться только FutureBuilder объектами, которые, в свою очередь, возвращают только Widget объекты.Мне просто нужно вернуть String, который я могу затем использовать для перехода к новому маршруту через объект MaterialPageRoute или для отображения ошибки пользователю без изменения маршрутов.Есть ли способ сделать это с Flutter?Возвращение виджета для меня бесполезно, так как я не хочу создавать новый виджет для отображения.Я использую Flutter 0.3.2 и Dart 2.0.0

В качестве упрощенного примера, когда мне нужно вызвать запрос к базе данных:

@override
Widget build(Buildcontext context) {
    return new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
            new Container(
                padding: const EdgeInsets.all(16.0),
                child: new TextField(
                    keyboardType: TextInputType.number,
                    controller: _controller,
                    decoration: new InputDecoration(
                    hintText: 'Zip Code',
                ),
                onSubmitted: (string) {
                  return string;
                },
              ),
            ),
            new RaisedButton(
                onPressed: () {
                        // use regex to test against user input
                        if (_controller.text != null && _controller.text.isNotEmpty) {
                            RegExp zipCodeRegExp = new RegExp(r"^(\d{5})$");

                            // if the user input validates...
                            if (zipCodeRegExp.hasMatch(_controller.text)) {
                            zipCode = _controller.text;

                           // need to perform database query here and return a string, not a Widget

                            } else {
                               // an else condition here
                            }
                        } else {
                           // an else condition here
                        }
                    }
                }
            ),
        ],
    );
}

Возможно, я не следую "мантре"Флаттера?Я ценю ваше внимание и вклад в это.

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

A Future - это просто семантический сахар для обратного вызова. Представь, что у тебя было:

void fetchName(void Function(String) callback);

void main() {
  fetchName((name) {
     print('Your name is: $name');
  });
}

Нет способа преобразовать (или извлечь ) name из fetchName. Он не существует до тех пор, пока обратный вызов не будет завершен, и обратный вызов может быть завершен не сразу (его можно прочитать из базы данных, например, из вашего примера, из сети и т. Д.).

Одним из преимуществ использования FutureBuilder является то, что оно действительно помогает разобраться в асинхронных абстракциях, таких как FutureStreamBuilder для Stream), и позволяет вы сосредоточены на написании (синхронного) кода строителя:

new FutureBuilder<String>(
  future: _calculation, // a Future<String> or null
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none: return new Text('Press button to start');
      case ConnectionState.waiting: return new Text('Awaiting result...');
      default:
        if (snapshot.hasError)
          return new Text('Error: ${snapshot.error}');
        else
          return new Text('Result: ${snapshot.data}');
    }
  },
)
0 голосов
/ 15 мая 2018

С тех пор я понял это (я верю, что именно это Гюнтер первоначально говорил, но фундаментальная причина, почему мне не было понятно в то время).Единственный способ использовать Future без создания объекта Widget - использовать API Future.API Future позволяет выполнять синтаксический анализ объекта Future, как если бы это был объект AsyncSnapshot (в этом месте можно проанализировать .data в функции FutureBuilder builder:).Это может быть выполнено для возвращенного объекта Future (который может использовать async с await).Например:

Future regionName = dbClient.getRegionNameFromZipCode(int.parse(zipCode)); <-- this database method getRegionNameFromZipCode returns a Future object and uses async and await

regionName.then((data) {
   String hZonesString = data[0]['hzone'];
   print(hZonesString);
}, onError: (e) {
     print(e);
   });

Это довольно просто, если вы понимаете, как можно использовать API Future, и это не против использования FutureBuilder.Полезно знать новичкам этого языка, таким как я!

0 голосов
/ 11 мая 2018

FutureBuilder - это просто удобный помощник для восстановления дерева виджетов после завершения Future.

Вы можете использовать

funcThatReturnsFuture().then((result) {
  print(result);
  setState(() {
    someVal = result;
  })
})

или

Future funcThatMakesAsyncCall() async {
  var result = await funcThatReturnsFuture();
  print(result);  
  setState(() {
    someVal = result;
  })
}

Основным ограничением является то, что вы не можете вернуть значение непосредственно вызывающей стороне без Future, потому что нет способа вернуться из асинхронного выполнения к синхронизации выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...