Flutter

[Flutter] RxDart 사용과 PublishSubject, BehaviorSubject

Black.bean 2021. 1. 22. 16:06

개요

RxDart는 Dart를 리액티브 프로그래밍이 가능하게 하는 라이브러리이다. 이번 포스트에서는 RxDart에서 생산 주체인 Subject와 위젯의 StreamBuilder를 활용하는 방법을 간단하게 소개한다. 추가로 PublishSubject와 BehaviorSubject도 소개한다.

 

Bloc.dart

class Bloc {
  List<MyStock> mStocks = [];
  BehaviorSubject<List<MyStock>> _subjectMyStockList;

  Bloc() {
    _subjectMyStockList = BehaviorSubject<List<MyStock>>.seeded(mStocks);
  }

  get myStockObservable => _subjectMyStockList.stream;

  insertFromMyStock(MyStock item) {
    mStocks.add(item);
    _subjectMyStockList.sink.add(mStocks);
  }


  dispose() {
    _subjectMyStockList.close();
  }
}

var bloc = Bloc();

 

Page.dart

Widget _buildMyStocksLayout() {
    return StreamBuilder<List<MyStock>>(
        stream: bloc.myStockObservable, //stream
        builder: (context, snapshot) { 
          if (snapshot.hasData && snapshot.data.length > 0) {
            return ListView(
              physics: NeverScrollableScrollPhysics(),
              shrinkWrap: true,
              children: _buildMyStockTile(snapshot.data),
            );
          } else {
            return ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemCount: 2,
                itemBuilder: (context, index) => Container(
                      margin: EdgeInsets.all(5),
                      child: Shimmer.fromColors(
                        baseColor: Colors.grey[200],
                        highlightColor: Colors.grey[100],
                        child: ListTile(
                          tileColor: Colors.grey[200],
                        ),
                      ),
                    ));
          }
        });
  }

 

In Bloc.dart

1. 먼저 관찰 대상이 되는 기본 자료형인 List<MyStock> mStocks를 생성한다.

2. 이벤트를 발행하는 주체인 BehaviorSubject를 생성하고 mStocks를 wrapping한다.

 

 

In Page.dart

3. 가장 상위 위젯을 StreamBuilder로 wrapping한다. (StreamBuilder는 Subscribe를 가능하게 하는 위젯으로 볼 수 있다.)

4. stream의 인자로 bloc의 BehaviorSubject의 stream을 할당하여 관찰을 수행할 수 있게 초기화한다.

 

 

이후  bloc의 insertMyStock 메서드가 호출되면 새로운 아이템이 추가되고 _subjectMyStockList.sink.add(mStocks);가 호출되어 위의 위젯에서 새로운 데이터에 대한 snapshot을 획득할 수 있다. 

 

추가로, bloc이 dispose 될 때 subject를 close한다.

 

참고. Subject의 종류

Subject는 크게 PublishSubject, BehaviorSubject로 나뉜다.

 

PublishSubject

PublishSubject는 정확히 구독(subscribe)를 시작한 시점부터의 데이터만 전송받을 수 있다.

PublishSubject의 스트림에서 빨간색, 녹색, 파란색이 순서대로 발행되는 상황이다. 두번째 화살표에선 빨간색이 발행되기 전에 구독을 시작하여 모든색을 수신한다. 하지만, 마지막 화살표는 녹색이 발행된 직후 구독하기 시작하여 파란색만 수신할 수 있다.

 

BehaviorSubject

BehaviorSubject의 경우 구독한 시점에서 가장 최신의 값을 받을 수 있다. 즉, 구독하자마자 구독하기 바로 직전 값을 받을 수 있다. 이후는 PublishSubject 처럼 순서대로 수신한다.

BehaviorSubject의 초기 값으로 분홍색이 존재하고 빨간색, 녹색, 파란색이 순서대로 발행되는 상황이다. 먼저 두번째 화살표에서 빨간색이 발행되기 전에 구독을 시작한다. 이 때, 가장 직전의 값인 초기값을 수신할 수 있다. 이후 빨간색, 녹색, 파란색을 순서대로 수신할 수 있다. 마지막 화살표의 경우 녹색이 발행된 후에 구독을 시작한다. 그럼에도 녹색은 가장 최신의 값이었기 때문에 녹색을 수신할 수 있다. 이후 파란색이 발행되어 수신한다. 추가로, 다이어그램에서 보이는 것 처럼 BehaviorSubject는 초기값인 seed가 필요하다.