Bloc의 Event 사용
Bloc의 Event 사용
현재 위젯 트리에 특정 Bloc이 제공되고 있으면, 해당 Bloc의 이벤트를 발생시키기 위해 BlocProvider.of<BlocType>(context)
를 사용하여 Bloc 인스턴스에 접근한 후, add
메서드를 호출하여 이벤트를 추가할 수 있습니다.
Bloc 이벤트 사용 방법
- Bloc 인스턴스에 접근하기:
BlocProvider.of<BlocType>(context)
를 호출하여 현재 위젯 트리에서 Bloc 인스턴스에 접근합니다. 여기서BlocType
은 사용하고자 하는 Bloc의 타입입니다. - 이벤트 추가하기:
add
메서드를 사용하여 Bloc에 이벤트를 추가합니다. 이 때, 이벤트는 Bloc의Event
타입이어야 합니다.
예시
다음은 버튼 클릭 시 MyBloc
에 MyEvent
를 추가하는 예시입니다.
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(),
),
)
context.read
사용하기
3. 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을 어떻게 찾고 참조하는지에 있습니다.
BlocProvider.of<EmailTextInputBloc>(context)
사용하기:BlocProvider.of
는 주어진context
를 기반으로 위젯 트리에서 가장 가까운EmailTextInputBloc
타입의BlocProvider
를 찾습니다.BlocProvider.of
는 위젯의build
메서드 내에서 호출될 때context
가BlocProvider
범위 내에 있는지 확인합니다.BlocProvider.of
는 위젯이 빌드될 때 호출되기 때문에, 위젯 트리에서 관련BlocProvider
의 위치에 민감합니다.
context.read<EmailTextInputBloc>().add(...)
사용하기:context.read
는Provider
패키지의 기능으로,context
를 사용하여 Bloc 인스턴스를 찾지만, 위젯의 빌드 과정에는 영향을 주지 않습니다.context.read
는 일반적으로initState
,dispose
, 이벤트 핸들러 등 위젯의 빌드 과정 외부에서 사용됩니다.context.read
는 위젯의 현재 빌드 상태와 관계없이 Bloc에 접근할 수 있으므로, 더 유연하게 Bloc에 접근할 수 있습니다.
주요 차이점:
BlocProvider.of
는 위젯이 빌드될 때 현재의context
를 기반으로 Bloc을 찾으므로, 위젯 트리의 구조에 민감합니다.context.read
는 위젯의 빌드 과정과 무관하게 Bloc에 접근할 수 있기 때문에, 이벤트 핸들러나 생명주기 메서드에서 더 자주 사용됩니다.
일반적으로, 위젯의 build
메서드 내에서 Bloc에 이벤트를 추가하는 경우 BlocProvider.of
를 사용하고, 그 외의 경우에는 context.read
를 사용하는 것이 일반적입니다.