[Dart] stream 사용법 -3, StreamController broadcast(multiple listen)
이번 포스팅에서는 StreamController의 broadcast에 대해 알아보겠습니다.
stream 사용법 -2에서는 single listen을 사용했었습니다. 리스너를 한개만 붙여서 사용할 수 있었습니다.
StreamController에는 여러개의 broadcast를 이용해 여러개의 listener를 사용할 수 있습니다.
1. StreamController.broadcast생성
2. Listener 추가
3. add, addStream
4. onListen, onResume, onPause, onCancel
5. 리스너 여러개 추가
5. close
실행 영상
1. StreamController 생성
여러개의 리스너를 사용하고 싶다면 생성할 때 broadcast 생성자를 사용해야 합니다.
  final streamController = StreamController.broadcast(
    onListen: () {
      print('onListen');
    },
    onCancel: () {
      print('onCancel');
    },
  );
2. Listener 추가
initState 함수에서 listen과 onDone 함수를 구현했습니다. 이제 stream에 데이터를 보내면 listen 함수에 타게됩니다.
  int value = 0;
  
  
  @override
  void initState() {
    streamController.stream.listen((event) {
      print('listen : $event');
      if (mounted) {
        setState(() {
          value += event as int;
        });
      }
    }).onDone(() {
      // streamController.close()를 호출하면 진입
      print('done : $value');
    });
    super.initState();
  }
3. Add
stream에 데이터를 보내는 것은 single streamcontroller와 동일합니다.
- 단일 데이터 전달
streamController.add(1)
- 스트림으로 전달
  streamController.addStream(countStream(5))
......
  Stream<int> countStream(int to) async* {
    for (int i = 1; i <= to; i++) {
      await Future.delayed(const Duration(milliseconds: 300));
      yield i;
    }
  }
4. onListen, onResume, onPause, onCancel
StreamController.broadcast에서는 onResumer과 onPause 함수는 사용 불가능합니다. 만약 호출했을 때 아래와 같은 오류 메세지를 볼 수 있습니다.
Unsupported operation: Broadcast stream controllers do not support pause callbacksonListen과 onCancel은 호출 가능합니다.
streamController.onListen?.call()
streamController.onCancel?.call()
4. 리스너 여러개 추가
다른 화면에서 두 개의 리스너를 추가해보겠습니다.
여러개의 화면이 있더라도 listener를 붙여놓은 화면이 살아있다면 데이터를 받을 수 있습니다.
- 두번째 화면에서 리스너 추가
  int value = 0;
  
  @override
  void initState() {
    widget.streamController.stream.listen((event) {
      print('listen second : $event');
      if (mounted) {
        setState(() {
          value += event as int;
        });
      }
    }).onDone(() {
      print('done : $value');
    });
    super.initState();
  }
- 세 번째 화면에서 리스너 추가
  int value = 0;
  @override
  void initState() {
    widget.streamController.stream.listen((event) {
      print('listen third : $event');
      if (mounted) {
        setState(() {
          value += event as int;
        });
      }
    }).onDone(() {
      print('done : $value');
    });
    super.initState();
  }
7. Close
close는 말 그대로 stream을 닫는 함수입니다. close를 호출한 후에 add를 한다면 오류가 발생합니다.
  @override
  void dispose() {
    streamController.close();
    super.dispose();
  }
Full code
코드가 길어져서 파일로 첨부했습니다. import에서 상대 경로로 추가해놨으니 같은 폴더에 넣고 사용하시면 됩니다.