Трепетать. Асинхронность (Async) <> Параллелизм (Изолировать). Совсем

Введение Недавно я с удивлением обнаружил, что мои коллеги не до конца понимают, что такое асинхронность во Flutter. Почему-то у них возникла мысль, что если асинхронную функцию написать правильно, то она не будет блокировать интерфейс.

Пролистав пару статей, я не смог найти простого, полного и понятного объяснения всей этой кухни (здесь все по принципу «выбирай 2 из 3»)).

В одной статье я даже прочитал, что в Dart есть какая-то замечательная асинхронность, которая позволяет отложить выполнение кода до тех пор, пока поток не освободится (что на мой взгляд немного вводит в заблуждение) (Примечание: в комментариях nikita_dol указал, что, вероятно, имелось в виду - РасписаниеЗадача ).

Для кого эта статья? Статья предназначена для тех, кто только начинает знакомиться с Flutter, поэтому в этой небольшой заметке я постараюсь на простом примере показать, что асинхронность — это всего лишь возможность выполнять код непоследовательно.

Но, если у вас «тяжелая» функция (даже если она трижды асинхронна), она все равно заблокирует ваш интерфейс.

Конечно, в реальном продукте вы вряд ли встретите столь явные проявления (процессоры на данный момент достаточно мощные), но разобраться в том, как это работает, все же стоит. Идти И так, возьмем для экспериментов пример из документации библиотеки флаттер_блок .

Немного модифицируем функцию «_mapTimerStartedToState» класса timer_bloc — закомментируем обновление счетчика, чтобы оно не мешало:

  
  
  
  
   

Stream<TimerState> _mapTimerStartedToState(TimerStarted start) async* { yield TimerRunInProgress(start.duration); _tickerSubscription?.

cancel(); // _tickerSubscription = _ticker // .

tick(ticks: start.duration) // .

listen((duration) => add(TimerTicked(duration: duration))); }

Добавим новую статическую (сделаем заранее такую — isolate работает только с ними) функцию:

static Future<void> _heavyComput (SendPort sendPort) async { await Future.delayed(Duration(seconds: 5)); print('======================='); print('!!!function finished!!!'); print('======================='); return null; }

Здесь, в качестве эмуляции тяжелых вычислений, мы ждем окончания 5-секундной задержки.

Модифицируем функцию mapEventToState — добавим в конце асинхронный вызов _heavyComput:

@override Stream<TimerState> mapEventToState( TimerEvent event, ) async* { .

.

.

_heavyComput(null); }

К первому испытанию все готово – наша задача наблюдать за волшебными волнами.

Запускаем и видим - волны волнуются, интерфейс не блокируется, через 5 секунд высвечивается сообщение об окончании функции.



Трепетать.
</p><p>
 Асинхронность (async) <> параллелизм (изолировать).
</p><p>
 Совсем Это чудесная асинхронность – паника была ложной.

Хм.

Что, если Future.delayed(Duration(секунд: 5)) заменить циклом?

static Future<void> _heavyComput(SendPort sendPort) async { int pause = 1200000000; for (int i = 0; i < pause; i++) {} print('======================='); print('!!!function finished!!!'); print('======================='); return null; }

Запускаем и все – приехали – волны больше не волнуются.



Трепетать.
</p><p>
 Асинхронность (async) <> параллелизм (изолировать).
</p><p>
 Совсем Думаю, особых пояснений здесь не требуется: даже асинхронная тяжелая функция все блокирует. По умолчанию весь код выполняется в одном потоке.

Просто в первом случае никаких расчетов не требовалось, нужно было просто подождать, а во втором расчеты были нужны.

Ну а чтобы статья не получилась совсем микроскопической, давайте вызовем эту функцию с помощью isolate. Давайте изменим mapEventToState:

@override Stream<TimerState> mapEventToState( TimerEvent event, ) async* { .

.

.

var _receivePort = ReceivePort(); var _isolate = Isolate.spawn(_heavyComput, _receivePort.sendPort); }

Запускаем его и видим, что интерфейс не заблокирован; сообщение о завершении функции получаем с заметной задержкой.



Трепетать.
</p><p>
 Асинхронность (async) <> параллелизм (изолировать).
</p><p>
 Совсем Вот и все (о том, как работают async и await — статей много, не думаю, что стоит на этом останавливаться).

Пример можно скачать по ссылке - flutter_timer_async_and_parallels Теги: #мобильная разработка #flutter #dart #async #isolat

Вместе с данным постом часто просматривают: