Menu
Coddy logo textTech

Stream の基礎

CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 77/110。

Future が単一の値を配信するのに対し、Stream は時間の経過とともに一連の値を配信します。複数のデータを放出できるパイプのようなものだと考えてください。イベント、リアルタイムの更新、またはデータを少しずつ処理するのに最適です。

Stream.fromIterable() や、async*yield を使用した非同期ジェネレータ関数を使用して、シンプルなストリームを作成できます:

Stream<int> countToThree() async* {
  yield 1;
  yield 2;
  yield 3;
}

Future<void> main() async {
  await for (var number in countToThree()) {
    print(number);
  }
}
// 出力: 1, 2, 3

async*キーワードは、Streamを返す関数を定義する際に使用し、yieldは各値を送出します。ストリームを処理するには、値が届くたびに順次処理を行うawait forを使用します。

また、コールバック関数を引数に取る listen() メソッドを使用して、ストリームをリッスンすることもできます。

Stream<String> greetings() async* {
  yield 'Hello';
  yield 'Hi';
  yield 'Hey';
}

void main() {
  greetings().listen((message) {
    print(message);
  });
}

Futureとの主な違いは、Futureは単一の値で一度だけ完了するのに対し、Streamは終了するまでに多くの値を放出できる点です。これにより、Streamはユーザーの操作、センサーの読み取り、または細切れに届くデータなどの継続的なデータを扱うのに理想的です。

challenge icon

チャレンジ

簡単

ストリームを使用して、時間の経過とともに値を放出するカウントダウンタイマーシステムを構築しましょう!カウントダウン数値のシーケンスを生成するクラスを作成し、ストリームが単一の値ではなく複数の値をどのように配信するかを学びます。

コードを2つのファイルに整理します:

  • countdown.dart: カウントダウンストリームを生成する Countdown クラスを作成します。クラスには以下を含める必要があります:
    • カウントダウンの開始数値を格納する start フィールド (int)
    • 開始数値を受け取るコンストラクタ
    • Stream<int> を返す countDown() メソッド。async*yield を使用して、start から 0(0を含む)までの数値を放出します
    • Stream<String> を返す countDownWithMessage() メソッド。これは、start から 1 までの各数値に対して 'T-minus [number]' という形式の文字列を放出し、最後に 'Liftoff!' を放出します
  • main.dart: カウントダウンファイルをインポートし、両方のストリームメソッドを実演します。main関数は async である必要があり、以下の処理を行います:
    • 3 から始まる Countdown インスタンスを作成します
    • 'Number countdown:' とプリントします
    • await for を使用して countDown() を反復処理し、各数値をプリントします
    • 空行をプリントします
    • 'Launch sequence:' とプリントします
    • await for を使用して countDownWithMessage() を反復処理し、各メッセージをプリントします

yield ステートメントがストリームを通じて値を放出し、await for が到着した各値を処理する様子に注目してください。1つの結果を配信する Future とは異なり、ストリームは複数の値を順番に放出します!

期待される出力:

Number countdown:
3
2
1
0

Launch sequence:
T-minus 3
T-minus 2
T-minus 1
Liftoff!

チートシート

Streamは、単一の値を返すFutureとは異なり、時間の経過とともに一連の値を配信します。ストリームは、イベント、リアルタイムの更新、またはデータを少しずつ処理するのに最適です。

async*yieldを使用した非同期ジェネレータ関数を使用してストリームを作成します:

Stream<int> countToThree() async* {
  yield 1;
  yield 2;
  yield 3;
}

await forを使用してストリームを処理します:

Future<void> main() async {
  await for (var number in countToThree()) {
    print(number);
  }
}

または、コールバックを指定してlisten()メソッドを使用します:

void main() {
  greetings().listen((message) {
    print(message);
  });
}

Stream.fromIterable()を使用して、イテラブルからストリームを作成することもできます。

自分で試してみよう

import 'countdown.dart';

Future<void> main() async {
  // TODO: 3から始まるCountdownインスタンスを作成する
  
  // TODO: 'Number countdown:' を出力する
  
  // TODO: await forを使用してcountDown()を反復処理し、各数値を出力する
  
  // TODO: 空行を出力する
  
  // TODO: 'Launch sequence:' を出力する
  
  // TODO: await forを使用してcountDownWithMessage()を反復処理し、各メッセージを出力する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン