[Flutter] StatelessWidget()_BLoC

Tyger·2021년 10월 18일
0

StatelessWidget()_BLoC

StatelessWidget의 state 관리를 위한 유명한 library들이 많다

BLoC, provider, GetX, Cubit 등이 많이 사용하는 상태 관리 라이브러리이고, 이 중에서 GetX만 사용해보지 못했다

개인적으로 배우기 쉽고 가벼운 프로젝트에서는 확실히 provider가 강력하다고 생각하고 사용은 못해봤지만 GetX도 배우고 싶을 정도로 장점이 많고 다양한 기능을 제공해준다
GetX reference는 한국어도 지원하여 다음에 GetX에 대해서도 정리해볼 생각임

좀 더 규모가 있는 project를 하게되면 현재는 거의 BLoC, Cubit을 사용하는 편이고 GetX는 localization, router 용도로 많이 사용하며 요새 provider는 거의 사용을 못하고 있다

이 글에서는 StatelessWidget()에 대해서만 간략하게 알아볼 예정이라 상태관리에 대해서는 설명 하지 않겠음

현재 작성된 코드는 기존 project에서 포스팅을 위해 작성된거라 code generator도 사용이 되고 있어 코드를 그대로 가져가도 실행이 되지 않음

조만간 간단하게 api를 사용하면서 Domain Driven Design을 기반으로 BLoC, Cubit, GetX, freezed code generator, getIt이라는 종속성 주입을 위한 라이브러리들로 실제 미니 프로젝트를 작성할 예정입니다

먼저 이전 글에서 작성된 코드랑 같은 코드에 BLoC pattern을 사용해서 상태 이벤트를 전달해서 UI를 그려주는 코드로 작성했다

UI

import 'package:ddd_practice_app/_velog/application/velog_bloc_stateless_bloc.dart';
import 'package:ddd_practice_app/injection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

  
  Widget build(BuildContext context) {
    return BlocProvider<VelogBlocStatelessBloc>(
      create: (context) => getIt<VelogBlocStatelessBloc>()
        ..add(const VelogBlocStatelessEvent.reset()),
      child: BlocBuilder<VelogBlocStatelessBloc, VelogBlocStatelessState>(
        builder: (context, state) {
          return Scaffold(
            appBar: AppBar(
              backgroundColor: Colors.white,
              title: const Text('Stateless'),
            ),
            body: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Padding(
                  padding: const EdgeInsets.only(bottom: 30),
                  child: Text(
                    state.count.toString(),
                    style: const TextStyle(
                        fontSize: 50, fontWeight: FontWeight.bold),
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    buttonForm(
                        context: context,
                        title: '+',
                        onTap: () {
                          context
                              .read<VelogBlocStatelessBloc>()
                              .add(const VelogBlocStatelessEvent.increment());
                        }),
                    buttonForm(
                        context: context,
                        title: '-',
                        onTap: () {
                          context
                              .read<VelogBlocStatelessBloc>()
                              .add(const VelogBlocStatelessEvent.decrement());
                        }),
                    buttonForm(
                        context: context,
                        title: 'RESET',
                        onTap: () {
                          context
                              .read<VelogBlocStatelessBloc>()
                              .add(const VelogBlocStatelessEvent.reset());
                        }),
                  ],
                ),
              ],
            ),
          );
        },
      ),
    );
  }

  Container buttonForm({
    required BuildContext context,
    required String title,
    required Function() onTap,
  }) {
    return Container(
      width: MediaQuery.of(context).size.width * 0.25,
      height: MediaQuery.of(context).size.height * 0.07,
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(18), color: Colors.deepOrange),
      child: InkWell(
        onTap: onTap,
        child: Center(
            child: Text(
          title,
          style: const TextStyle(
              fontSize: 25, fontWeight: FontWeight.bold, color: Colors.white),
        )),
      ),
    );
  }
}

body에 buttonForm() 메서드에 onTap 부분의 event 부분을 보면 값을 1씩 증가시키는 increment(), 1씩 차감하는 decrement(), 0으로 초기화 시키는 reset() 부분이 있다

이 부분에서 발생하는 event가 state에 전달되어 UI를 변경하게 해주는 역할이다

 context.read<VelogBlocStatelessBloc>()
 .add(const VelogBlocStatelessEvent.increment());
context.read<VelogBlocStatelessBloc>()
.add(const VelogBlocStatelessEvent.decrement());
context.read<VelogBlocStatelessBloc>()
 .add(const VelogBlocStatelessEvent.reset());

bloc.dart

  
  Stream<VelogBlocStatelessState> mapEventToState(
    VelogBlocStatelessEvent event,
  ) async* {
    yield* event.map(
      reset: (e) async* {
        yield state.copyWith(count: 0);
      },
      increment: (e) async* {
        yield state.copyWith(count: state.count + 1);
      },
      decrement: (e) async* {
        yield state.copyWith(count: state.count - 1);
      },
    );
  }

event.dart


class VelogBlocStatelessEvent with _$VelogBlocStatelessEvent {
  const factory VelogBlocStatelessEvent.reset() = _Reset;
  const factory VelogBlocStatelessEvent.increment() = _Increment;
  const factory VelogBlocStatelessEvent.decrement() = _Decrement;
}

state.dart


class VelogBlocStatelessState with _$VelogBlocStatelessState {
  factory VelogBlocStatelessState({
    required int count,
  }) = _VelogBlocStatelessState;
  factory VelogBlocStatelessState.initial() => VelogBlocStatelessState(
        count: 0,
      );
}

BLoC은 이렇게 bloc.dart, event.dart, state.dart 3개의 파일로 구성하여 상태 관리를 한다

앞서 설명한 내용처럼 BLoC에 대해서는 다음에 더 자세히 다루겠음

Example

profile
Flutter Developer

0개의 댓글