Bloc의 Event 사용

Bloc의 Event 사용

현재 위젯 트리에 특정 Bloc이 제공되고 있으면, 해당 Bloc의 이벤트를 발생시키기 위해 BlocProvider.of<BlocType>(context)를 사용하여 Bloc 인스턴스에 접근한 후, add 메서드를 호출하여 이벤트를 추가할 수 있습니다.

Bloc 이벤트 사용 방법

  1. Bloc 인스턴스에 접근하기: BlocProvider.of<BlocType>(context)를 호출하여 현재 위젯 트리에서 Bloc 인스턴스에 접근합니다. 여기서 BlocType은 사용하고자 하는 Bloc의 타입입니다.
  2. 이벤트 추가하기: add 메서드를 사용하여 Bloc에 이벤트를 추가합니다. 이 때, 이벤트는 Bloc의 Event 타입이어야 합니다.

예시

다음은 버튼 클릭 시 MyBlocMyEvent를 추가하는 예시입니다.

ElevatedButton(
  onPressed: () {
    // 현재 위젯 트리에서 MyBloc 인스턴스에 접근
    BlocProvider.of<MyBloc>(context).add(MyEvent());
  },
  child: Text('Send Event'),
)

이 예시에서는 ElevatedButton 위젯의 onPressed 콜백에서 BlocProvider.of<MyBloc>(context)를 호출하여 MyBloc 인스턴스에 접근하고, MyEvent를 추가합니다.

주의 사항

  • BlocProvider.of<BlocType>(context) 호출 시, 해당 타입의 Bloc이 현재 위젯 트리에서 제공되고 있는지 확인해야 합니다. 그렇지 않으면 런타임 에러가 발생할 수 있습니다.
  • BlocProvider.of<BlocType>(context)BuildContext가 Bloc의 범위 내에 있을 때 사용할 수 있습니다. 즉, Bloc을 제공하는 위젯이 현재 위젯보다 상위에 위치해야 합니다.
  • Bloc의 이벤트를 발생시킬 때는 앱의 상태 관리 전략과 일관성을 유지하는 것이 중요합니다. 이벤트는 상태 변화를 유발하는 데 사용되므로, 이벤트 처리 로직을 명확하게 정의해야 합니다.

현재 위젯 트리에 특정 Bloc이 제공되고 있지 않다면

현재 위젯 트리에 특정 Bloc이 제공되고 있지 않다면, 해당 Bloc에 직접 접근하려 할 때 BlocProvider.of 메서드를 사용하면 런타임 에러가 발생합니다. 이 상황을 처리하는 몇 가지 방법이 있습니다:

1. Bloc을 상위 위젯에서 제공하기

Bloc이 필요한 위젯의 상위에 BlocProvider를 배치하여 Bloc을 제공합니다. 이렇게 하면 하위 위젯에서 BlocProvider.of를 사용하여 Bloc에 접근할 수 있습니다.

BlocProvider<MyBloc>(
  create: (context) => MyBloc(),
  child: MyWidget(), // 여기서 MyBloc에 접근 가능
)

2. Repository를 사용하여 Bloc 생성하기

만약 Bloc이 특정 서비스나 데이터에 의존하고 있다면, 이를 RepositoryProvider를 사용하여 제공하고, Bloc 내부에서 필요한 서비스나 데이터를 주입받아 사용할 수 있습니다.

RepositoryProvider<MyRepository>(
  create: (context) => MyRepository(),
  child: BlocProvider<MyBloc>(
    create: (context) => MyBloc(context.read<MyRepository>()),
    child: MyWidget(),
  ),
)

3. context.read 사용하기

context.read<BlocType>()BlocProvider.of<BlocType>(context)와 유사하게 Bloc 인스턴스에 접근할 수 있도록 합니다. 하지만 read는 위젯이 빌드되는 동안이 아니라, 이벤트 핸들러나 initState와 같은 생명주기 메서드에서 사용됩니다.

context.read<MyBloc>().add(MyEvent());

4. Bloc을 생성자 매개변수로 전달하기

필요한 Bloc을 직접 생성하여 위젯의 생성자를 통해 전달할 수도 있습니다. 이 방법은 테스트 용이성을 높이고, 위젯의 결합도를 낮추는 데 도움이 될 수 있습니다.

class MyWidget extends StatelessWidget {
  final MyBloc myBloc;

  MyWidget({Key? key, required this.myBloc}) : super(key: key);

  // ...
}

주의 사항

  • Bloc이 필요한 위젯보다 상위에 BlocProvider가 위치하지 않는다면, Bloc에 접근할 수 없습니다. 이는 BlocProvider의 범위(scope) 문제입니다.
  • context.read는 위젯 트리의 현재 상태를 고려하지 않으므로, 위젯이 빌드되는 도중에는 사용하지 않는 것이 좋습니다.
  • Bloc을 생성자 매개변수로 전달하는 방법은 의존성 주입을 명시적으로 만들며, 테스트와 유지보수에 유리하지만, 위젯 트리가 복잡해질 수 있습니다.

BlocProvider.of과 context.read의 차이점

BlocProvider.of<EmailTextInputBloc>(context).add(EmailTextInputChangedEvent(email));context.read<EmailTextInputBloc>().add(EmailTextInputChangedEvent(email)); 사이의 주요 차이점은 위젯 트리에서 Bloc을 어떻게 찾고 참조하는지에 있습니다.

  1. BlocProvider.of<EmailTextInputBloc>(context) 사용하기:
    • BlocProvider.of는 주어진 context를 기반으로 위젯 트리에서 가장 가까운 EmailTextInputBloc 타입의 BlocProvider를 찾습니다.
    • BlocProvider.of는 위젯의 build 메서드 내에서 호출될 때 contextBlocProvider 범위 내에 있는지 확인합니다.
    • BlocProvider.of는 위젯이 빌드될 때 호출되기 때문에, 위젯 트리에서 관련 BlocProvider의 위치에 민감합니다.
  2. context.read<EmailTextInputBloc>().add(...) 사용하기:
    • context.readProvider 패키지의 기능으로, context를 사용하여 Bloc 인스턴스를 찾지만, 위젯의 빌드 과정에는 영향을 주지 않습니다.
    • context.read는 일반적으로 initState, dispose, 이벤트 핸들러 등 위젯의 빌드 과정 외부에서 사용됩니다.
    • context.read는 위젯의 현재 빌드 상태와 관계없이 Bloc에 접근할 수 있으므로, 더 유연하게 Bloc에 접근할 수 있습니다.

주요 차이점:

  • BlocProvider.of는 위젯이 빌드될 때 현재의 context를 기반으로 Bloc을 찾으므로, 위젯 트리의 구조에 민감합니다.
  • context.read는 위젯의 빌드 과정과 무관하게 Bloc에 접근할 수 있기 때문에, 이벤트 핸들러나 생명주기 메서드에서 더 자주 사용됩니다.

일반적으로, 위젯의 build 메서드 내에서 Bloc에 이벤트를 추가하는 경우 BlocProvider.of를 사용하고, 그 외의 경우에는 context.read를 사용하는 것이 일반적입니다.

Last Updated:
Contributors: RiGang