Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- permission
- consumer
- borderRadius
- ListView.builder
- datetime
- Swift
- transform
- changenotifier
- Camera
- swift 문법
- changenotifierprovider
- Snapshot
- reference
- setstate
- 문법
- switch
- snackbar
- divider
- Stream
- signout
- multiprovider
- provider
- runTransaction
- enum
- user
- globalkey
- Navigator
- controller
- platformexception
- Firebase
Archives
- Today
- Total
코딩하는 제리
[Flutter/Dart]비동기 프로그래밍 : Stream 본문
- 스트림은 데이터나 이벤트가 들어오는 통로
- 데이터의 추가나 변경이 일어나면 이를 관찰하던 곳에서 처리
main() {
var stream = Stream.periodic(Duration(seconds: 1), (x) => x).take(10);
// 0에서 9까지 1씩 10초동안 1초 간격으로 출력
// stream.listen(print);
// 0에서 18까지 2씩 10초동안 1초 간격으로 출력
stream.listen((int number) => print(number + number));
}
/*
* 스트림은 항상, 만들기 -> 연결(listen) -> 데이터 처리의 과정을 거친다.
* 1. Stream.periodic()에서 일정 시간마다 데이터(이벤트)를 만든다.
* 2. listen()을 한다. 스트림에서 만들어지는 이벤트를 관찰하기 시작한다.
* 3. listen에서 적은대로 데이터를 다룬다. 여기서는 listen(print)라고 적었기에 출력만 한다.
*/
여러 방법으로 Stream 만들기
main() {
// 일반적인 데이터를 처리할 때
Stream.fromIterable([1,2,3,4,5]).listen((int x) => print('iterable : $x'));
// 반복적인 처리
Stream.periodic(Duration(seconds: 1), (x) => x) // 1초에 한번씩 동작
.take(5) // 5개 까지만 데이터를 처리
.listen((x) => print('take : $x'));
// 비동기 처리
Stream.fromFuture(getData()).listen((x) => print('from Future : $x'));
}
Future<String> getData() async {
// 5초간 대기
await Future.delayed(Duration(seconds: 5));
print("Fetched Data");
return "5초 기다렸다가 온 데이터입니다.";
}
결과
iterable : 1
iterable : 2
iterable : 3
iterable : 4
iterable : 5
take : 0
take : 1
take : 2
take : 3
take : 4
Fetched Data
from Future : 5초 기다렸다가 온 데이터
처음, 끝의 데이터만 사용하기
맨 앞의 데이터만 쓸 수도 있고, 맨 마지막의 데이터만 쓸 수도 있다.
main() {
// 가장 앞의 데이터만 가져옴. 결과 : 1
var stream = Stream.fromIterable([1,2,3,4,5]);
stream.first.then((value) => print("stream.first: $value"));
// 가장 마지막의 데이터만 가져옴. - 결과 : 5
stream = Stream.fromIterable([1,2,3,4,5]);
stream.last.then((value) => print("stream.first: $value"));
// 데이터가 비어있는지 확인. 결과 : false
stream = Stream.fromIterable([1,2,3,4,5]);
stream.isEmpty.then((value) => print("stream.isEmpty: $value"));
// 데이터 전체 길이. 결과 : 6
stream = Stream.fromIterable([10,20,30,40,50,60]);
stream.length.then((value) => print("stream.length: $value"));
}
스트림은 기본적으로 싱글 서브스크립션(Single Subscription)이다. 한 군데에서만 리슨 할 수 있다.
여러 군데에서 사용하려면 브로드캐스트(Broadcast)로 변경해줘야 한다.
스트림 변경(StreamTransformer)
map을 쓰면 스트림을 어느 정도 변경할 수 있다.
main() {
// 0.2초 간격으로 3개의 데이터에 +10
var streamMap = Stream.periodic(Duration(milliseconds: 200), (x) => x)
.take(3)
.map((x) => x + 10);
streamMap.listen(print);
}
// 결과
10
11
12
하지만 복잡한 처리는 힘들다.
StreamTransformer를 사용하면 스트림 변경에 유리.
import 'dart:async';
main() {
// sink는 스트림 이벤트를 받아들이는 곳
var transformer = StreamTransformer.fromHandlers(handleData: (value, sink) {
sink.add("First: $value");
sink.add("Second: $value");
});
var stream = Stream.fromIterable(["Good",1,2,3,4,5]);
stream.transform(transformer).listen((value) => print("listen : $value"));
}
// 결과
listen : First: Good
listen : Second: Good
listen : First: 1
listen : Second: 1
listen : First: 2
listen : Second: 2
listen : First: 3
listen : Second: 3
listen : First: 4
listen : Second: 4
listen : First: 5
listen : Second: 5
async*, yield
함수를 사용해서 스트림을 만드려면?
// async*은 yeild를 사용한다는 의미
Stream<int> createStream(List<int> numbers) async* {
for (var number in numbers) {
yield number; // return과 유사.
}
}
main() {
var numStream = createStream([1,3,5,7,9]); // 스트림 생성
numStream.listen((int number) => print(number)); // 스트림 데이터를 받아서 출력
}
함수로 만든 스트림도 이전처럼 동작. 차이점은 async*와 yield를 써서 만들었다는 점이다.
- async* : 제너레이터를 만든다는 뜻. 제너레이터는 뒤늦게 데이터 연산을 할 때 쓰인다. 미리 연산을 하지 않고,
미루어 두었다가 요청이 있을때 처리한다. - yield : return과 유사. return은 한번 리턴하면 함수가 종료되지만, yield는 열린 채로 있어서 필요할 때 다른 연산을 수행할 수 있다.
Broadcast Stream
기본적으로 만들어지는 스트림은 한 곳에서만 listen할 수 있다.
여러 곳에서 listen을 하려면 브로드캐스트를 사용
import 'dart:async';
main() {
var sc = StreamController.broadcast();
var broadcastStream = sc.stream;
broadcastStream.listen((v) => print('broadcast1 $v'));
broadcastStream.listen((v) => print('broadcast2 $v'));
sc.add(10);
sc.add(20);
}
// 결과
broadcast1 10
broadcast2 10
broadcast1 20
broadcast2 20
각각의 데이터를 따로 처리하는 걸 알 수 있다.
같은 데이터를 다르 뷰에서 처리할 때 효과적.
'Flutter' 카테고리의 다른 글
[Flutter/Project] vscode로 프로젝트 시작하기 (0) | 2021.01.11 |
---|---|
[Flutter] 맥에서의 플러터 개발 환경 설정 (0) | 2021.01.11 |
[Flutter] 해킨토시에서의 개발 환경 (0) | 2021.01.11 |
Comments