동도리 개발 로그

플러터(Flutter) BLoC 패턴 본문

개발/Flutter

플러터(Flutter) BLoC 패턴

동돌이 2019. 12. 9. 16:07
반응형

Flutter 개발하는 도중 알게된 BLoC 패턴 React개발 당시 Redux와 같은 목표를 가지고 구글에서 만들어진 Flutter 상태관리 패턴이다. Bussiness Logic Component 의 약자이다.

 

Provider도 있지만 그것은 나중에

 

디자인 패턴이기에 Flutter 말고도 React나 다른 프레임워크에도 적용 가능 하다고 한다.

 

BLoC 생김새

BLoC 에서 각 UI 객체 들은 BLoC 객체를 구독하고 있다.

 

BLoC 객체의 상태가 변경되면, BLoC 의 상태를 구독중인 UI 객체 들은 그 즉시 해당 상태로 UI 를 변경한다.

 

BLoC 객체는 UI 객체로 부터 이벤트를 전달받으면, BLoC 객체는 필요한 Provider 나 Repository 로 부터 데이터를 전달받아, Bussiness Logic 을 처리한다.

 

Bussiness Logic 을 처리한후, BLoC 객체를 구독중인 UI 객체 들에게 상태를 전달한다.

 

class BLoC {
    provider: Provider = new Provider();
    stream: Subject = new Subject();
    async sink() {
        const data = await Provider.getCounterModel();
        const result = await this.BussinessLogic(data);
        this.stream.next(result);
    }
    private async BussinessLogic() {
        // ...
    }
}

UI 객체는 구독중이던 BLoC 객체의 상태가 변경되면 상태를 전달받는데, 이때 얻은 상태를 이용하여 화면을 재구성한다.

 

class UI {
    bloc = new BLoC();
    constructor() {
        this.bloc.stream.subscribe((data) => {
            this.render(data);
        });
    }
    render(data) {
        return (
            <div onClick={this.bloc.sink}>
                {data}
            </div>
        )
    }
}

아래를 하기전 해야할 사항 

dependencies를 추가 해줘야한다. 그냥 import한다고 다되면 좋겠지만...

 

pubspec.yaml 파일의 dependencies: 에 추가한다.

  dependencies:
  	flutter:
    		sdk: flutter
    #아래부분 추가
  	rxdart: ^0.22.6
  	shared_preferences: ^0.5.4+8

Flutter의 BLoC

Flutter에서는 stream을 이용해서 BLoC를 구현한다. 

 

rxdart의 PublishSubject를 이용해서 컨트롤러를 생성하고 sink, stream 을 이용하여 값을 넣고 구독하는 역할을 구현해놨다.

 

authorization_bloc.dart

import 'package:rxdart/rxdart.dart';

class LoginBloc extends Validators {
  Repository repository = Repository();
  
  //PublishSubject는 rxdart 패키지 안에 존재한다.
  final PublishSubject _loadingData = PublishSubject<bool>();
  
  Observable<bool> get loading => _loadingData.stream;
  
  login(String email, String password) async {
    String token = await repository.login(email, password);
    //PublishSubject로 만들어진 StreamController를 사용해서 sink.add를 실행한다.
    _loadingData.sink.add(false);
    authBloc.openSession(token);
  }
  
  void dispose() {
    _loadingData.close();
  }
}

 

app.dart

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

	//기존 로컬레포지토리에 로그인정보(토큰)가 있는지 없는지 확인하여 BLoC에 sink.add 하는 부분
    authBloc.restoreSession();

    return MaterialApp(
      title: 'Login Demo Bloc',
      theme: ThemeData(
        primaryColor: Colors.blue,
      ),
      home: createContent(),
    );
  }

  Widget createContent() {
    return StreamBuilder<bool> (
      stream: authBloc.isSessionValid,
      builder: (context, AsyncSnapshot<bool> snapshot) {
        if(snapshot.hasData && snapshot.data) {
          return HomeScreen();
        }else{
          return LoginScreen();
        }
      }
    );
  }
}

 

 

Flutter에서는 Rxdart를 이용해서 sink 사용가능하다. 

 

Redux와 BLoC의 차이점

State 관리를 위한다는 점에서는 Redux와 BLoC는 같지만 차이점이 있다.

 

BLoC는 UI가 확인 한다는 것( subscribe ) 한다는 것이다.

 

그래서 BLoC의 내용을 확인하는 것또한 Stream 으로 내용을 가져온다.

 

따라서 BLoC에 접근하는 UI부분이 없다고 하더라도 stream을 subscribe하고 있고 BLoC 에서 상태가 변경되면 UI는 최신상태로 변경된다.

 

 

마치며

BLoC를 다뤘는데  구글에서는 올해 Google IO (2019) 에서 상태 관리 패턴으로 Provider를 추천 하였다.

BLoC는 작년 (2018)에 추천한 패턴이고 provider는 올해 추천한 패턴이다.

 Provider 또한 공부하고 글을 쓰겠지만 잠깐 본것으로는 Provider 가 쉽게 구현이 가능하지만 큰 프로젝트에서는 BLoC패턴을 추천한다고 하는 것을 어디선가 본것 같다. 

 

아무튼 이쁘고, 잘, 문제없이, 빠르게 돌아가면 되니까 더 공부 해서 좋은 방향으로 프로젝트를 진행 하려한다. 

반응형