Flutter BloC 디자인 패턴

야민·2022년 7월 24일
1

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개의 댓글