Flutter BloC 디자인 패턴

야민·2022년 7월 24일

Bloc은 Business Logic Component의 약자로 UI와 Business Logic을 분리하기 위한 디자인 패턴입니다.
rxdart 패키지를 사용하여 간소 구현합니다.

Bloc 패턴은 UI와 비지니스 로직을 분리하여 코드를 효율적으로 관리할 수 있도록 하는 디자인 패턴입니다.

한 화면상에 많은 위젯이 포함되어 있다면 화면을 새로고침 할 때 마다 불필요한 위젯까지 함께 새로고침 되어 부하를 발생시킬 수 있습니다.
Bloc 패턴에서는 각 Bloc마다 대응되는 하위 UI요소가 있으며 값의 변경을 인지하여 값의 변경을 확인하고 필요한 UI요소만을 업데이트 합니다.
또한 비지니스 로직이 분리되었기 때문에 기능만을 따로 테스트할 수 있습니다.

Bloc 디자인 패턴을 사용하기 위해서는 값의 변경을 인지할 수 있어야 합니다.
rxdart패키지를 사용하여 변경을 인지하고 bloc 디자인 패턴을 구현합니다.

프로젝트 폴더 구조

  • bloc
    bloc 제어, 비지니스 로직 저장
  • components / resource
    분리한 위젯을 저장
  • models
    필요한 클래스, 구조 저장
  • ui
    화면에 표시되는 페이지 저장

test_bloc.dart

import ...

class TestBloc {
  var initTest = '/// init';

  //bloc singleton
  //static final TestBloc _instance = TestBloc._internal();

  final _testSubject = BehaviorSubject();
  Stream get test => _testSubject.stream;

  TestBloc() {
    _testSubject.sink.add(initTest);
  }

  dynamic fetchData() async {
    await Future.delayed(const Duration(milliseconds: 1000), () {});
    return '/// click';
  }

  void click() async {
    var test = await fetchData();
    _testSubject.sink.add(test);
  }
  
  void dispose() {
    _testSubject.close();
  }
}

test_view.dart

import ...

class TestView extends StatelessWidget {
  TestView({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextButton(
          onPressed: () {
            //bloc 비지니스 로직 호출
            //해당 bloc이 생성된 곳의 변수를 불러옵니다.
            testBloc.click();
          },
          child: const Text(
            'Click',
          ),
        ),
        Container(
          child: StreamBuilder(
            stream: testBloc.testResult,
            initialData: 'start',
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if(snapshot.hasData) {
                return Text(snapshot.data.toString());
              }
              return Container();
            }
          ),
        ),
      ],
    );
  }
}

test_page.dart

import ...

//bloc
late TestBloc testBloc;

class TestPage extends StatefulWidget {
  TestPage() {}
  
  State<TestPage> createState() => _MainPageState();
}

class _MainPageState extends State<TestPage> {

  void initState() {
    super.initState();
    //bloc 생성
    testBloc = TestBloc();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bloc'),
      ),
      //bloc과 대응되는 UI Component
      body: TestView(),
    );
  }
}

0개의 댓글