Flutter. Асинхронные функции.

Предисловие.

В этой статье я расскажу как создавать асинхронные функции. Т.е. функции которые запускаются в отдельном потоке.

Но сначала разберем отличия синхронных и асинхронных функций.

Синхронные и асинхронные функции.

  • Синхронные функции это те функции которые выполняются в одном потоке. Т.е. действия выполняются последовательно.
  • Асинхронные функции, выполняются в новом потоке. Т.е. действия выполняются параллельно.

Создание асинхронного счетчика.

Откройте предыдущий проект из урока про StatefulWidget. И код _NewWidgetState замените на это:

class _NewWidgetState extends State<NewWidget> {
  int _counter = 0;

  startTimer() async {
    for (int i = 0; i < 100; i++) {
      await Future.delayed(
        Duration(
          milliseconds: 100,
        ),
      );
      _counter++;
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          children: [
            Text("Count $_counter"),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          startTimer();
        },
        child: Text("Start"),
      ),
    );
  }
}

Рассмотрим его.

startTimer() async {

Данной строкой, я создал асинхронную функцию startTimer. Данная запись, является упрощенной версией этой записи.

Future startTimer() async {

Кратко о Future.

Future — это асинхронный тип который, должна возвращать любая асинхронная функция (на подобии Promise из JS). Тип Future это как void для синхронных функций. Если же хотите вернуть значение из асинхронной функции, то укажите тип возвращаемого значения, в треугольных скобках Future<>. Например так.

Future<bool> tempAsyncFunc() async {
  return false;
}

Возвращаемся к коду.

Далее, я создал цикл, который отсчитывает до 100.

for (int i = 0; i < 100; i++) {

И воспользовался методом Delayed объекта Future, туда передал Duration, чтобы сделать задержку в 100 мс.

await Future.delayed(
  Duration(
    milliseconds: 100,
  ),
);

Ключевое слово await, ждет асинхронную функцию, т.е. делает асинхронную функцию, синхронной.

_counter++;
setState(() {});

Далее, я увеличил счетчик на единицу и обновил виджеты с помощью setState.

Функцию startTimer рассмотрели, далее, её я повесил на floatingActionButton.

floatingActionButton: FloatingActionButton(
  onPressed: () {
    startTimer();
  },
  child: Text("Start"),
),

Саму же кнопку я изменил, заменив иконку на текст Start. По итогу, мы получили программу, которая при нажатии на кнопку start, запускает счетчик в отдельном потоке, который считает до 100, и отрубается.

Итоговый результат.