[Flutter] Stream

박준형·2025년 1월 22일

Stream 이란?

스트림은 데이터나 이벤트가 들어오는 흐름이다.

언제 데이터가 들어올 지 알기 어려운 것을 비동기(async) 작업으로 처리할 때 스트림이 사용된다.

Future이랑 다른 점은 아래 사진 참고.

즉 데이터를 연속적으로 처리할 때 사용되는 것이다. (채팅 메시지처럼)

https://api.dart.dev/stable/2.2.0/dart-async/Stream-class.html

공식 문서의 설명 링크이다.

내용이 많지만 크게 보면 스트림은 두가지 형태가 있다.

1. Single-subscription 스트림

Single-subscription 스트림은 이름에서도 알 수 있듯이 구독하는 리스너가 하나이다.

import 'dart:async';

void main() {
  final controller = StreamController(); // StreamController 선언
  final stream = controller.stream; // Stream 가져오기

  // Stream에 listen() 함수를 실행하면 값이 주입될 때마다 콜백 함수를 실행할 수 있습니다.
  final streamListener1 = stream.listen((val) {
    print(val);
  });

  // Stream에 값을 주입하기
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
}

▼ 실행 결과
1
2
3
4

2. Broadcast 스트림

Broadcast는 리스너가 둘 이상일 때 사용한다.

import 'dart:async';

void main() {
  final controller = StreamController();

  // 여러 번 리슨할 수 있는 Broadcast Stream 객체 생성
  final stream = controller.stream.asBroadcastStream(); // asBroadcastStream() 얘를 사용해야한다.

  // 첫 번째 listen() 함수
  final streamListener1 = stream.listen((val) {
    print('listening 1');
    print(val);
});

  // 두 번째 listen() 함수
  final streamListener2 = stream.listen((val) {
    print('listening 2');
    print(val);
  });

  // add()를 실행할 때마다 listen()하는
  // 모든 콜백 함수에 값이 주입됩니다.
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
}

▼ 실행 결과
listening 1
1
listening 2
1
listening 1
2
listening 2
2
listening 1
3
listening 2
3

스트림을 만드는 방법

스트림을 만드는 방법은 다양하다. 위의 예제처럼 StreamController를 사용해도 되고, async*를 사용해 사용자 정의 함수를 만들어도 된다. 구체적인 방법은 적지 않겠다..

스트림을 다루는 방법

내가 아는건 두가지 방법이 있는데, StreamSubscription이랑 저번에 포스팅 했던 StreamBuilder를 이용하는 것이다. 전자는 데이터 처리를 위한 비즈니스 로직에서 주로 사용되고, 후자는 UI를 리빌드 하는데에 사용되는 것이다. 역시 구체적인 방법은 적지 않겠다..

나는 플래너 앱을 만들때 drift데이터베이스에서 지원하는 stream을 이용해 함수를 내가 생성한 일정을 볼 수 있는 함수를 만들고 이를 StreamBuilder를 이용해서 일정을 볼 수 있게끔 UI를 리빌드 해줬다.

(  
  tables: [
    Schedules,
  ],
)
class LocalDatabase extends _$LocalDatabase {
  LocalDatabase() : super(_openConnection());

  Stream<List<Schedule>> watchSchedules(DateTime date) =>
      (select(schedules)..where((tbl) => tbl.date.equals(date))).watch(); // 데이터를 조회하고 변화를 감지
Expanded(
            child: StreamBuilder<List<Schedule>>(
                stream: GetIt.I<LocalDatabase>().watchSchedules(selectedDay),
                builder: (context, snapshot) {
                  ...

추후 drift를 다루는 방법도 포스팅 하겠다.

출처
https://www.youtube.com/watch?v=YojoXx383TI&t=164s
https://wikidocs.net/227916

profile
unleash the beast

0개의 댓글