- 스트림은 흐름, 파도라고 이해할 수 있고, 데이터나 이벤트가 들어오는 통로를 뜻한다.
- 스트림을 사용한다면 지속적으로 데이터의 흐름을 관찰할 수 있다.
- 데이터를 만드는 곳과 소비하는 곳을 따로 둘 수 있다.
- 비동기 작업을 할 때 주로 쓰이며, 일련의 비동기 이벤트와 같다고 할 수 있다.
예시를 들자면, 1초마다 데이터를 만드는 스트림을 만든다고 하자
void main(){
var stream = Stream.periodic(Duration(seconds: 1), (x) => x).take(10);
stream.listen(print);
}
-> Stream.periodic에서 1초마다 이벤트를 발생시키고, stream은 이벤트를 listen하여 print한다
또 다른 예시를 들어보자.
poistion 데이터를 position이 바뀔때마다 데이터를 반환하는 스트림을 만든다고 하자.
먼저 position 스트림을 Geolocator 를 사용해 받아온다.
Geolocator.getPositionStream(desiredAccuracy: LocationAccuracy.high)
.listen((pos) {
position = pos;
});
이 코드를 이해해보면, Geolocator 클래스의 getPositionStream을 통해 Position 스트림을 받아왔고, 이 스트림은 position 데이터가 바뀔때마다 이벤트가 발생할 것이다.
그리고 이 스트림을 listen해 position data를 pos로 받아와 position에 입력하고 있다.
위 Geolocator의 스트림은 위치가 바뀔때만 이벤트가 발생한다. 데이터의 변화와 상관없이 1초마다 position을 받는 스트림을 만들어보자.
Stream<Position> positionStream =
Stream<Position>.periodic(Duration(seconds: 1), (_) => position);
간단하게, 1초마다 지역변수인 position 데이터을 받아오는 또 다른 Position 스트림을 만들었다.
Geolocator.getPositionStream(desiredAccuracy: LocationAccuracy.high)
.listen((pos) {
_position = pos;
});
_positionStream =
Stream<Position>.periodic(Duration(seconds: 1), (_) => position);
이 생성한 PositionStream을 사용해보자.
StreamSubscription sub = _positionStream.listen((pos) => {
_position = position
});
sub.cancel()
PositionStream을 구독하는 streamSubscription을 만들었고, 이제 data를 받을 수 있다
cancel()로 구독 취소도 가능하다
지금까지는 단일 구독으로, 한곳에서만 listen할 수 있었다.
만약 여러곳에서 listen이 필요하다면, StreamController의 broadcast를 이용할 수 있다.
final StreamController<Position> _controller =
StreamController<Position>.broadcast();
Geolocator.getPositionStream(desiredAccuracy: LocationAccuracy.high)
.listen((pos) {
_position = pos;
});
Stream _positionStream =
Stream.periodic(Duration(seconds: 1), (_) => controller.add(position));
구독은 선언된 StreamController를 이용하여 listen한다.
controller.stream.listen((pos){
position = pos
})
지금까지 쓴 코드를 통해, 두곳의 프로바이더가 한 곳의 스트림을 동시에 listen하도록 만들어보았다.
싱글톤 클래스를 생성한 후, getter로 broadcast controller를 받을 수 있도록 했다.
class AProvider with ChangeNotifier {
final PositionStream _positionStream = PositionStream();
void subscriptionA(){
_positionStream.controller.stream.listen((pos){
// 작업
})
}
}
class BProvider with ChangeNotifier {
final PositionStream _positionStream = PositionStream();
void subscriptionB(){
_positionStream.controller.stream.listen((pos){
// 작업
})
}
}
두 곳에서 모두 1초마다 position 데이터를 받을 수 있다.