[flutter] - RxDart : Stream Classes Part2


Stream Classes

각 내용들을 이어서 하나씩 알아보자


ReapetStream

  • Example :
      RepeatStream((int repeatCount) =>
      Stream.value('repeat index: $repeatCount'), 3)
      .listen((i) => print(i)); // Prints 'repeat index: 0, repeat index: 1, repeat index: 2'
    

Repeat은 말그대로 Stream이 종료되었을 때 다시 Stream을 생성하며 Listen도 다시 반복한다.

repeatCount를 지정하지 않을 경우 무한히 반복된다.

Stream.value('repeat index: $repeatCount'), 3)

뒤에 있는 숫자가 repeatCount


RetryStream

  • Example :
      RetryStream(() { Stream.fromIterable([1]); })
      .listen((i) => print(i)); // Prints 1
    
      RetryStream(() {
       Stream.fromIterable([1])
          .concatWith([ErrorStream(Error())]);
     }, 1)
     .listen(print, onError: (e, s) => print(e)); // Prints 1, 1, RetryError
    
      Rx.retry(() { Stream.value(1); })
      .listen((i) => print(i); // Prints 1
    
      Rx
     .retry(() {
       Stream.value(1).concatWith([Stream.error(Error())]);
     }, 1)
     .listen(print, onError: (e, s) => print(e); // Prints 1, 1, RetryError
    

RetryRepeat Rxdart문서를 보면 똑같이 설명되있다. 하지만 다르게 동작한다.

Repeat은 횟수만큼 반복동작하지만 Retry는 성공할 때까지 반복한다.

RxDart 공식 문서에는 설명이 햇갈리게 되있어서 issue를 등록해봤다.


RetryWhenStream

  • Example :
      bool errorHappened = false;
      RetryWhenStream(
      () => Stream
          .periodic(const Duration(seconds: 1), (i) => i)
          .map((i) {
              if (i == 3 && !errorHappened) {
              throw 'We can take this. Please restart.';
              } else if (i == 4) {
              throw 'It\'s enough.';
              } else {
              return i;
              }
          }),
          (e, s) {
              errorHappened = true;
              if (e == 'We can take this. Please restart.') {
                  return Stream.value('Ok. Here you go!');
              } else {
                  return Stream.error(e);
              }
          },
      ).listen(
          print,
          onError: (e, s) => print(e),
      ); // Prints 0, 1, 2, 0, 1, 2, 3, RetryError
    

Retry와 이름은 비슷하지만 행동은 복잡하다.

먼저 Retry와 비슷하게 정상적인 경우에는 똑같이 동작한다. 하지만 위의 코드와 같이 에러가 발생하게되면 아래쪽 retryWhenFactory이 동작하게 된다. 그곳에서는 에러 내용을 보고 정상 동작을 시켜줄 수 있으며 그 곳에서도 error가 발생하게되면 종료하게된다.


SequenceEqualStream

  • Example :
      SequenceEqualStream(
      Stream.fromIterable([1, 2, 3, 4, 5]),
      Stream.fromIterable([1, 2, 3, 4, 5])
      )
      .listen(print); // prints true
    
      SequenceEqualStream(
      Stream.fromIterable([1, 2, 3, 4, 5]),
      Stream.fromIterable([1, 2, 3, 4, 5]),
      equals: check)
      .listen(print); 
    

SequenceEqual은 이름과 같이 내부 데이터의 순서가 중요하다. 순서가 동일할 경우 True 틀릴 경우 False를 반환한다. 아래 코드처럼 equals에 함수를 넣을 경우 함수의 내용대로 비교하여 True, False를 반환한다.

이것도 API문서에서 example코드가 잘못되있다…


SwitchLatestStream

  • Example :
      final switchLatestStream = SwitchLatestStream<String>(
      Stream.fromIterable(<Stream<String>>[
          Rx.timer('A', Duration(seconds: 2)),
          Rx.timer('B', Duration(seconds: 1)),
          Stream.value('C'),
      ]),
      );
    
      // Since the first two Streams do not emit data for 1-2 seconds, and the 3rd
      // Stream will be emitted before that time, only data from the 3rd Stream
      // will be emitted to the listener.
      switchLatestStream.listen(print); // prints 'C'
    

SwitchLatest은 여러 Stream중에서 가장 마지막에 들어온 StreamListen하게 된다.

  • Example :
      final switchLatestStream = SwitchLatestStream<String>(
          Stream.fromIterable(<Stream<String>>[
          Stream.fromIterable(['a', 'b', 'c']),
          Stream.fromIterable(['d', 'e', 'f']),
          Rx.timer('A', Duration(microseconds: 2)),
          Rx.timer('B', Duration(seconds: 1)),
          Stream.fromIterable(['g', 'h', 'i']),
          ]),
      );
    
      switchLatestStream.listen(print); // prints a d g h i 
      // 첫번쨰 스트림 a b c
      // 두번째 스트림 d e f
      // 세번째 스트림 g h i
      // 에서 가장 마지막 stream인 g h i 리슨
    

예시를 보면 마지막으로 데이터가 들어온 [g h i]listen하게 된다.

Duration이 들어간 stream은 무시되는듯 하다.


TimerStream

  • Example :
      TimerStream('hi', Duration(minutes: 1))
          .listen((i) => print(i)); // print 'hi' after 1 minute
    

TimerDuration후에 주어진 데이터를 출력한다.


CombineLatestStream

  • Example :
      CombineLatestStream.list<String>([
          Stream.fromIterable(['a']),
          Stream.fromIterable(['b']),
          Stream.fromIterable(['C', 'D'])])
      .listen(print); //prints ['a', 'b', 'C'], ['a', 'b', 'D']
    

CombineLatest는 주어진 Stream들을 결합하여 출력한다.

이미지

  • Example :
      CombineLatestStream(
          [
              Stream.fromIterable(['a']),
              Stream.fromIterable(['b']),
              Stream.fromIterable(['C', 'D'])
          ],
          (values) => values.last
      )
      .listen(print); //prints 'C', 'D'
    

    이 예제에서는 들어오는 데이터들(a b C , a b D)의 마지막 C D가 출력된다.

  • Example :
      CombineLatestStream.combine2(
      Stream.fromIterable([1]),
      Stream.fromIterable([2, 3]),
      (a, b) => a + b,
      )
      .listen(print); // prints 3, 4
    

이 예제에서는 들어온 데이터들을 조합하여 출력할 수 있다. (1, 2 3) => (1+2, 1+3)


ForkJoinStream

  • Example :
      ForkJoinStream.list<String>([
          Stream.fromIterable(['d', 'a']),
          Stream.fromIterable(['b']),
          Stream.fromIterable(['C', 'D'])
      ]).listen(print); //prints ['a', 'b', 'D']
    

ForkJoinStream그룹에서 가장 마지막 값만 모아서 출력해줍니다. 화면 로딩에서 많은 requests후에 유용합니다.

  • Example :
      CombineLatestStream(
      [
          Stream.fromIterable(['a']),
          Stream.fromIterable(['b']),
          Stream.fromIterable(['C', 'D'])
      ],
      (values) => values.last
      )
      .listen(print); //prints 'D'
    

이 예제에서는 CombineLatest와 다르게 마지막 값이 a b D이기 때문에 마지막 값 D가 출력됩니다.

  • Example :
      ForkJoinStream.combine2(
      Stream.fromIterable([1]),
      Stream.fromIterable([2, 3]),
      (a, b) => a + b,
      )
      .listen(print); // prints 4
    

이 예제에서도 CombineLatest와 비슷하게 출력 결과물에 함수를 사용하여 조작이 가능하지만 결과 값은 가장 마지막 데이터인 4만 출력됩니다.


RangeStream

  • Example :
      RangeStream(1, 3).listen((i) => print(i)); // Prints 1, 2, 3
    
      RangeStream(3, 1).listen((i) => print(i)); // Prints 3, 2, 1
    

Range는 범위를 지정해주고 사이 데이터들을 순서대로 출력해줍니다.

숫자만 가능


ZipStream

  • Example :
      ZipStream(
          [
          Stream.fromIterable(['A']),
          Stream.fromIterable(['B']),
          Stream.fromIterable(['C', 'D']),
          ],
          (values) => values.join(),
      ).listen(print); // prints 'ABC'
    

Zip은 주어진 Stream들을 index에 맞춰서 zip function을 실행한 데이터를 출력한다. 여기서 zip function

(values) => values.join()

이미지

  • Example :
      ZipStream.zip3(
          Stream.fromIterable(['A', 'Z']),
          Stream.fromIterable(['B', 'Q', 'F']),
          Stream.fromIterable(['C', 'D', 'G']),
          (a, b, c) => a + b + c,
      ).listen(print); // prints 'ABC' , 'ZQD'
    

Zip은 값에 대한 특별한 zip함수 실행을 위해 Zip2~Zip9까지 지원하며 뒤에 숫자는 Stream갯수이다.


Classes 끝

이로써 Classes를 모두 알아봤고 다음은 Extension Methods를 알아보자