Study/Development

[개발일지] Flutter Bloc 상태관리 #2 Bloc Widgets

titann 2023. 4. 6. 16:38

Flutter Bloc

<인프런 개발하는 남자 온라인강의 수강일지>


Flutter Bloc Widgets

BlocProvider

  • 지연생성 옵션(lazy): false(사용 시점에서 동시에 사용)
  • 하위 계층 위젯들에서 접근 가능
  • Bloc 생성 후 메모리 반환의 경우 자동으로 해준다

return BlocProvider(
      create: (context) => SampleBloc(),
      lazy: true,
      child: SamplePage(),
    );

MultiBlocProvider

  • BlocProvider 다중 등록

return MultiBlocProvider(
      providers: [
        BlocProvider(create: ((context) => SampleBloc())),
        BlocProvider(create: ((context) => SampleSecondsBloc())),
      ],
      child: SamplePage(),
    );

RepositoryProvider

  • Repository + Provider, Repository(저장소)를 제공하는 위젯
  • 지연생성 옵션(lazy) 통해 관리할 수 있다.
  • 저장소 데이터를 가공할 수 있는 데이터베이스 or 외부 api 통신 등 관리할 때

return RepositoryProvider(
      create: (context) => RepositorySample(),
      child: BlocProvider(
        create: (context) => SampleBlocDI(context.read<RepositorySample>()),
        child: SamplePage(),
      ),
    );

MultiRepositoryProvider

  • RepositoryProvider 다중 등록

return MultiRepositoryProvider(
      providers: [
        RepositoryProvider(
          create: (context) => RepositorySample(),
        ),
        RepositoryProvider(
          create: (context) => RepositorySecondSample(),
        )
      ],
      child: BlocProvider(
        create: (context) => SampleBlocDIMulti(
          context.read<RepositorySample>(),
          context.read<RepositorySecondSample>(),
        ),
        child: SamplePage(),
      ),
    );

BlocBuilder

  • BlocProvider로 생성된 bloc을 사용할 때 쓰는 widget
  • bloc 옵션을 사용하지 않고 사용 시 현 context로부터 bloc을 찾아 변화 감지
  • bloc을 지정하는 케이스의 경우 특별한 케이스에서 사용 권장
  • buildWhen 옵션을 통해 필요한 조건일 때만 변화를 줄 수 있다.

child: BlocBuilder<SampleBloc, int>(
          buildWhen: (previous, current) {
            return current > 10;
          },
          builder: (context, state) {
            return Text(
              'index : $state',
              style: const TextStyle(fontSize: 70),
            );
          },
        ),

BlocListener

  • 상태변화에 따른 이벤트만 처리가 필요할 때 사용되는 widget
  • *child위젯의 경우 rebuild가 발생되지 않는다.
  • 사용되는 예
    • 특정 상태가 변경 되었을 때 메시지 팝업을 띄워야 하는 상황
    • bloc간 통신이 필요할 때.

child: BlocListener<SampleBloc, int>(
          listenWhen: (previous, current) => current > 5,
          listener: (context, state) {
            _showMessage(context);
          },
          child: Text(
            context.read<SampleBloc>().state.toString(),
            style: const TextStyle(fontSize: 70),
          ),
        ),

MultiBlocListener

  • BlocListener 다중 등록

BlocConsumer

  • BlocBuilder와 BlocListener를 합쳐 놓은 위젯
  • 이벤트도 처리하면서 동시에 화면도 변경 해줘야 할 때
  • buildWhen과 listenWhen 조건을 통해 적절한 때에만 변경 및 이벤트처리 가능

child: BlocConsumer<SampleBloc, int>(
          listenWhen: (previous, current) => current > 5,
          listener: (context, state) {
            _showMessage(context);
          },
          buildWhen: (previous, current) => current % 2 == 0,
          builder: (context, state) => Text(
            state.toString(),
            style: const TextStyle(fontSize: 70),
          ),
        ),

BlocSelector

  • Bloc의 상태 중 필요한 부분만 선택적으로 필터링하여 변경에 도움을 주는 widget

BlocSelector<BlocSelectorBloc, BlocSelectorState, bool>(
              selector: (state) => state.changeState,
              builder: (context, state) {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ElevatedButton(
                        onPressed: () {
                          context
                              .read<BlocSelectorBloc>()
                              .add(ChangeStateEvent());
                        },
                        child: Text('상태변경')),
                    const SizedBox(width: 15),
                    ElevatedButton(
                        onPressed: () {
                          state
                              ? context
                                  .read<BlocSelectorBloc>()
                                  .add(ValueEvent())
                              : null;
                        },
                        child: Text('더하기')),
                  ],
                );
              },
            ),
반응형