[Flutter/Dart] Stream과 broadcast로 백그라운드 위치 수집하기(position stream)

찌니·2022년 10월 14일
1

Flutter

목록 보기
2/13

Stream

  • 스트림은 흐름, 파도라고 이해할 수 있고, 데이터나 이벤트가 들어오는 통로를 뜻한다.
  • 스트림을 사용한다면 지속적으로 데이터의 흐름을 관찰할 수 있다.
  • 데이터를 만드는 곳과 소비하는 곳을 따로 둘 수 있다.
  • 비동기 작업을 할 때 주로 쓰이며, 일련의 비동기 이벤트와 같다고 할 수 있다.

예시를 들자면, 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()로 구독 취소도 가능하다

Stream-broadcast

지금까지는 단일 구독으로, 한곳에서만 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
})

Stream-broadcast 예시

지금까지 쓴 코드를 통해, 두곳의 프로바이더가 한 곳의 스트림을 동시에 listen하도록 만들어보았다.

PositionStream.dart

싱글톤 클래스를 생성한 후, getter로 broadcast controller를 받을 수 있도록 했다.

AProvider.dart

class AProvider with ChangeNotifier {
  final PositionStream _positionStream = PositionStream();
  
  void subscriptionA(){
  	_positionStream.controller.stream.listen((pos){
    // 작업
    })
  }
}

BProvider.dart

class BProvider with ChangeNotifier {
  final PositionStream _positionStream = PositionStream();
  
  void subscriptionB(){
  	_positionStream.controller.stream.listen((pos){
    // 작업
    })
  }
}

두 곳에서 모두 1초마다 position 데이터를 받을 수 있다.

profile
찌니's develog

0개의 댓글