streamasynclistenMahir6 mnt baca

Stream di Dart

Data yang mengalir terus: Stream, listen, await for, dan broadcast stream.

Dari Future ke Stream

Future memberikan satu nilai di masa depan. Tapi bagaimana dengan data yang datang berulang-ulang? Update lokasi GPS, pesan chat masuk, harga saham berubah: ini butuh Stream, yaitu aliran nilai sepanjang waktu.

dart
Stream<int> hitungMundur() async* {
  for (int i = 3; i >= 1; i--) {
    await Future.delayed(Duration(seconds: 1));
    yield i; // kirim nilai ke pendengar, lalu lanjut
  }
}

void main() async {
  await for (var angka in hitungMundur()) {
    print(angka); // 3... 2... 1... (tiap detik)
  }
  print('Mulai!');
}
  • async* (bintang) menandai fungsi generator stream
  • yield mengirim satu nilai ke stream tanpa menghentikan fungsi
  • await for mendengarkan sampai stream selesai

listen: cara manual

dart
Stream<int> angka() async* {
  for (int i = 1; i <= 5; i++) {
    await Future.delayed(Duration(milliseconds: 300));
    yield i;
  }
}

void main() {
  angka().listen(
    (data) => print('Dapat: $data'),
    onDone: () => print('Stream selesai'),
    onError: (e) => print('Error: $e'),
  );
}

listen() mengembalikan StreamSubscription yang bisa di-cancel. Di Flutter, subscription yang lupa di-cancel adalah sumber memory leak klasik.

Mengubah stream: map, where

Stream punya operator mirip List:

dart
Stream<int> angka() async* {
  for (int i = 1; i <= 6; i++) {
    yield i;
  }
}

void main() async {
  await for (var x in angka().where((n) => n.isEven).map((n) => n * 10)) {
    print(x); // 20, 40, 60
  }
}

Ada juga operator lanjutan seperti debounce (di package rxdart) untuk menunda sampai user berhenti mengetik, sangat berguna untuk search-as-you-type.

Catatan teknis: Secara default stream itu single-subscription: cuma boleh didengarkan sekali. listen kedua akan error "Stream has already been listened to". Kalau butuh banyak pendengar (mis. beberapa widget mendengar data yang sama), ubah jadi broadcast stream dengan .asBroadcastStream(). Tapi ingat: broadcast stream tidak menyimpan event yang lewat sebelum ada pendengar.

StreamController: bikin stream sendiri

Kadang kamu yang memproduksi event, bukan sekadar mendengar:

dart
import 'dart:async';

void main() async {
  var controller = StreamController<String>();

  controller.stream.listen((pesan) => print('Chat: $pesan'));

  controller.add('Halo!');
  controller.add('Apa kabar?');
  await Future.delayed(Duration(milliseconds: 100));
  await controller.close();
}

StreamController punya dua sisi: add() untuk mengirim, stream untuk didengar. Pola ini adalah fondasi BLoC, salah satu state management paling populer di Flutter.

Stream di Flutter: StreamBuilder

Alasan stream wajib dipelajari: Flutter punya widget StreamBuilder yang otomatis rebuild UI setiap ada data baru. Chat realtime, live score, sensor: semuanya stream di balik layar. Memahami konsepnya di Dart murni membuat StreamBuilder terasa natural, bukan sihir.

Kapan Future, kapan Stream?

SituasiPakai
Ambil data sekali (HTTP GET)Future
Data datang berulang (chat, sensor)Stream
Progress upload/downloadStream
Simpan ke databaseFuture

Aturan praktis: kalau operasinya punya "selesai" yang jelas dan satu hasil, Future cukup. Kalau datanya mengalir terus tanpa akhir yang pasti, pakai Stream.