Skip to content

Latest commit

 

History

History
100 lines (71 loc) · 6.22 KB

File metadata and controls

100 lines (71 loc) · 6.22 KB

重要概念#2-3: 非同期プログラミング(Futureとasync/await)

Flutterでネットワーク通信やデータベースアクセスなど、時間のかかる処理を扱う時、必ず「非同期プログラミング」という考え方が必要になります。

このドキュメントでは、Futureasyncawaitという3つのキーワードを中心に、非同期プログラミングの基本を、レストランのウェイターの仕事に例えて解説します。

1. なぜ非同期処理が必要か? - シングルスレッドの問題

Dart(Flutterが使う言語)は、基本的にシングルスレッドで動作します。これは、「一度に一つの作業しかできない」ということです。

もし、すべての処理を「同期的(順番通り)」に行うとどうなるでしょうか?

  • 同期的なウェイターの仕事:
    1. お客さんAから注文を取る。
    2. キッチンに注文を伝え、料理が完成するまでその場でずっと待ち続ける。
    3. 料理が完成したら、お客さんAに運ぶ。
    4. ようやく、次のお客さんBの注文を取りに行く。

このウェイターは、キッチンの作業が終わるまで他の仕事を一切できません。その間、お客さんB、C、D...は、注文すらできずにイライラして待つことになります。

Flutterアプリも同じです。もし、重いネットワーク通信(料理)が終わるまでUIの更新(次の注文)をブロックしてしまうと、**アプリは完全にフリーズしてしまいます。**これではユーザー体験は最悪です。

2. 非同期処理とは「待ち時間を有効活用する」技術

この問題を解決するのが非同期プログラミングです。

  • 非同期的な(優秀な)ウェイターの仕事:
    1. お客さんAから注文を取る。
    2. キッチンに注文を伝え、「料理ができたら教えてね」とだけ言って、その場を離れる。
    3. キッチンの待ち時間に、お客さんBの注文を取ったり、お客さんCに水を運んだりする。
    4. キッチンから「料理できましたよ!」と声がかかったら、料理を受け取ってお客さんAに運ぶ。

このウェイターは、待ち時間を他の作業に充てることで、レストラン全体を効率的に回しています。アプリのUIもフリーズすることなく、サクサク動き続けます。

3. Dartにおける非同期プログラミングの主役たち

Dartでは、この「優秀なウェイターの仕事」を、Futureasyncawaitという3つのキーワードで実現します。

Future - 「未来にもらえる引換券」

Futureは、時間のかかる非同期処理の結果を表すオブジェクトです。

  • これは、レストランで注文した時にもらえる「料理の引換券」のようなものです。
  • 注文した瞬間(非同期処理を開始した瞬間)に、すぐにこのFuture(引換券)が手渡されます。
  • この引換券は、現時点ではまだ料理そのものではありませんが、「未来に、この引換券と引き換えに、料理(本当の結果)が手に入りますよ」という約束を表しています。
  • Future<String>なら「未来にString型のデータが手に入る引換券」、Future<int>なら「未来にint型のデータが手に入る引換券」という意味になります。
// ネットワークからユーザー名を取得する(かもしれない)関数
Future<String> fetchUserName() {
  // 3秒後に 'Taro' という名前を返す処理をシミュレート
  return Future.delayed(Duration(seconds: 3), () => 'Taro');
}

asyncawait - ウェイターの動きを実現する魔法の言葉

このFuture(引換券)を、簡単かつ直感的に扱うためのシンタックスシュガー(便利な書き方)がasyncawaitです。

  • async(アシンク):

    • 関数の定義の後ろにasyncと付けると、その関数は「非同期的な作業を含む、優秀なウェイターの関数ですよ」という宣言になります。
    • asyncが付いた関数は、必ず戻り値がFutureでラップされます(StringFuture<String>になる)。
  • await(アウェイト):

    • async関数の中でしか使えません。
    • Futureオブジェクトの前にawaitを付けると、「このFuture(引換券)が、本物の結果(料理)に変わるまで、ここで一旦処理を中断して、他の仕事をどうぞ」という意味になります。
    • 処理は中断しますが、アプリ(UIスレッド)はフリーズしません。
    • そして、Futureの結果が返ってきたら、そこから処理を再開します。

コード例

// ユーザー名を取得して、挨拶を表示する関数
Future<void> greetUser() async { // 1. この関数は非同期処理を含む宣言 (async)
  print('ユーザー名を取得します...');

  // 2. fetchUserName()が完了するまで、ここで待つ (await)
  //    でも、アプリはフリーズしない!
  String userName = await fetchUserName();

  // 3. 上のawaitが完了した後、この行が実行される
  print('こんにちは, $userName さん!');
}

void main() {
  greetUser();
  print('greetUser()の呼び出しは完了しました。結果を待っています...');
}

実行結果:

ユーザー名を取得します...
greetUser()の呼び出しは完了しました。結果を待っています...
(3秒後)
こんにちは, Taro さん!

greetUser()を呼び出した後、すぐに次のprint文が実行されていることに注目してください。これが、アプリがフリーズしない証拠です。

非同期プログラミングは、AIとのAPI連携やデータベース操作など、現代のアプリ開発に不可欠なスキルです。この「ウェイターと引換券」のイメージを掴めば、きっとマスターできるはずです。