フラッター。非同期(非同期)<>並列処理(分離)。まったく

前書き



最近、同僚がFlutterの非同期性を完全に明確にしていないことに驚きました。何らかの理由で、非同期関数が正しく記述されていれば、インターフェースをブロックしないという考えがありました。いくつかの記事をスクロールしても、このキッチン全体の簡単で完全で明確な説明は見つかりませんでした(すべてが原則に従っています-「3つから2つを選択してください」))。ある記事では、Dartには素晴らしい非同期性があることを読みました。これにより、スレッドが解放されるまでコードの実行を延期できます(私の意見では少し誤解を招く可能性があります)(注:コメント内) nikita_dolおそらく何を意味するのかを指摘- scheduleTask)。



誰のための記事



この記事は、Flutterに慣れ始めたばかりの人を対象としているため、この小さなメモで簡単な例を示して、非同期はコードを順番に実行する機能ではないことを示します。ただし、「重い」関数がある場合(3回非同期であっても)、インターフェイスはブロックされます。もちろん、実際の製品では、このような明らかな兆候に遭遇する可能性は低いですが(現時点では、プロセッサは非常に強力です)、それがどのように機能するかを理解する価値はあります。



行く



それでは実験用のflutter_blocライブラリのドキュメントから例を見てみましょう timer_blocクラスの「_mapTimerStartedToState」関数を少し変更してみましょう。干渉しないように、カウンターの更新をコメントアウトします。



Stream<TimerState> _mapTimerStartedToState(TimerStarted start) async* {
  yield TimerRunInProgress(start.duration);
  _tickerSubscription?.cancel();
  // _tickerSubscription = _ticker
  //     .tick(ticks: start.duration)
  //     .listen((duration) => add(TimerTicked(duration: duration)));
}

      
      







新しい静的関数を追加しましょう(事前にこのようにします-分離はそれらでのみ機能します)関数:



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秒後に機能の終了に関するメッセージが表示されます。







これは素晴らしい非同期です-パニックは誤りでした。うーん... Future.delayed(Duration(seconds: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;
}

      
      





私たちはそれを起動し、それだけです-「到着」-波はもはや心配しません。







ここではあまり説明は必要ないと思います。非同期の重い関数でさえすべてをブロックします。デフォルトでは、すべてのコードは1つのスレッドで実行されます。最初のケースでは計算は必要ありませんでしたが、待つ必要があり、2番目のケースでは計算が必要でした。



さて、記事が完全に微視的であることが判明しないように、分離を使用してこの関数を呼び出しましょう。 mapEventToStateを変更しましょう:



@override
Stream<TimerState> mapEventToState(
  TimerEvent event,
) async* {
. . .
  var _receivePort = ReceivePort();
  var _isolate = Isolate.spawn(_heavyComput, _receivePort.sendPort);
}

      
      







それを開始し、インターフェースがブロックされていないことを確認します。顕著な遅延を伴う関数の完了に関するメッセージを受け取ります。







それだけです(非同期でawaitが機能する方法-記事はたくさんありますが、そこで止まるべきではないと思います)。



例はリンクからダウンロードできます -flutter_timer_async_and_parallels



All Articles