1. bloc에 이은 flutter_bloc
bloc 포스팅에 이은 flutter_bloc 에 대해 알아보자. bloc은 dart로 만들어진 작은 컴포넌트 단위의 라이브러리이고 이것이 실제로 flutter에 적용하기 위해 쓰인 flutter_bloc에 대해 알아보자.
공식문서를 보게되면 패키지를 사용하기 전에 주의깊게 문서를 읽어보라는 당부의 메세지(?)가 있다. 그래서 한번 잘 숙지해두고 사용하자. 이론을 숙지하지 못한 상태의 개발은 나중에 언젠가 문제가 될수 있으니!
이전 포스팅인 여기에서 보자
2022.07.19 - [Mobile/Flutter] - [flutter] Bloc 이란? - official document
2022.07.19 - [Mobile/Flutter] - [flutter] flutter_bloc 이란?(Bloc Widgets) - official document
2022.07.19 - [Mobile/Flutter] - [flutter] Bloc Usage - official document
2. Bloc Widgets (링크)
1)BlocBuilder
BlocBuilder는 Bloc과 Builder 함수가 필요한 flutter widget이다. BlocBuilder는 새로운 상태의 응답으로 위젯을 만드는것을 처리한다. 마치 StreamBuilder와 비슷하지만 더 필요한 보일러플레이트 코드의 양을 줄이기 위해 더 간단한 api를 가진다. build 함수는 잠재적으로 많이 호출될 것이고, 상태에 대한 response로 위젯을 리턴하는 순수함수로 작성해야한다.
네비게이션이나, 다이얼로그 띄우는것 등의 상태에 대한 응답으로 무언가를 하고싶다면 BlocListener를 봐라.
아래는 3가지의 예시를 보여준다
// Bloc의 매개변수가 생략되면 BlocBuilder는
// 자동으로 BlocProvider와 현재의 BuildContext를 사용해 Lookup을 수행함
BlocBuilder<BlocA, BlocAState>(
builder: (context, state) {
// BlocA의 상태를 기반으로 하는 위젯을 리턴
}
)
// 해당 위젯에서만 사용하고, 상위 BlocProvider나 현재 BuildContext를 통해
// 접근할 수 없는 Bloc을 만드려는 경우에만 local Bloc을 만들어야한다.
BlocBuilder<BlocA, BlocAState>(
bloc: blocA, // local bloc 인스턴스를 제공
builder: (context, state) {
// BlocA의 상태를 기반으로 하는 위젯을 리턴
}
)
//빌더 함수가 선택적으로 호출되는 시점에 대해 세밀한 제어를 위해 buildWhen을 제공할 수 있다.
//buildWhen 함수는 이전 bloc과 현재 bloc 상태와 boolean 값을 리턴한다.
//true를 리턴하면 builder 는 만들어질 위젯과 state를 호출한다.
//false를 리턴하면 builder는 state를 호출하지 않고 재빌드 하지 않는다.
BlocBuilder<BlocA, BlocAState>(
buildWhen: (previousState, state) {
// return true/false to determine whether or not
// to rebuild the widget with state
},
builder: (context, state) {
// BlocA의 상태를 기반으로 하는 위젯을 리턴
}
)
2) BlocSelector
BlocSelector는 BlocBuilder와 유사하지만 개발자가 현재 bloc 상태를 기반으로 새 값을 선택하여 업데이트를 필터링할 수 있는 Flutter 위젯입니다.(말이 어려운데 한마디로 선택한것만 업데이트 하겠다는 의미?) 선택된 값이 변하지 않는다면 불필요한 빌드를 예방할 수 있다. builder가 다시 호출해야하는지를 BlocSelector가 정확히 판단하려면 선택된 값은 immutable 해야한다.
bloc 매개변수가 빠져있다면 BlocBuilder는 자동으로 BlocProvider와 현재의 BuildContext를 사용해 Lookup을 수행한다
BlocSelector<BlocA, BlocAState, SelectedState>(
selector: (state) {
// 제공된 state를 기반으로 선택한 state를 리턴한다
},
builder: (context, state) {
// 선택한 state를 기반으로한 위젯을 리턴한다.
},
)
3) BlocProvider
BlocProvider는 BlocProvider.of<T>(context)를 통해 자식에게 bloc을 제공하는 Flutter 위젯이다. 종속성 주입(DI) 위젯으로 사용되어 bloc의 단일 인스턴스가 하위 트리 내의 여러 위젯에 제공될 수 있다.
대부분의 경우 BlocProvider는 다른 하위 트리에서 사용할 수 있는 새 bloc 을 만드는 데 사용해야 한다. 아래 경우 BlocProvider는 Bloc 생성을 담당하므로 close는 자동으로 처리한다
기본적으로 BlocProvider는 bloc을 느리게 생성한다. 즉, BlocProvider.of<BlocA>(context)를 통해 bloc을 조회할 때 create가 실행된다. 그래서 이것을 재정의하고 create가 즉시 실행되도록 하려면 lazy를 false로 설정할 수 있다.
BlocProvider(
// lazy: false, // lazy create 변경, default - true
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
가끔? BlocProvider는 위젯 트리의 새 부분에 기존 bloc을 제공하는 데 사용할 수 있다. 이것은 기존 bloc 을 새로운 위치에서 사용할 수 있어야 할 때 일반적으로 사용된다. 이 경우 BlocProvider는 bloc을 생성하지 않았기 때문에 자동으로 close 하지 않는다.(close는 필요에 따라 진행..?)
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
그러면 아래의 예시를 사용해서 BlocA를 찾을 수 있다
// with extensions
context.read<BlocA>();
// without extensions
BlocProvider.of<BlocA>(context)
4) MultiBlocProvider
MultiBlocProvider는 여러 BlocProvider 위젯을 하나로 병합하는 Flutter 위젯이다. 가독성을 향상시키고 여러 BlocProvider를 중첩할 필요가 없다.
//BlocProvider 를 중첩으로 사용함.
//BlocProvider<BlocA>(
// create: (BuildContext context) => BlocA(),
// child: BlocProvider<BlocB>(
// create: (BuildContext context) => BlocB(),
// child: BlocProvider<BlocC>(
// create: (BuildContext context) => BlocC(),
// child: ChildA(),
// )
// )
//)
// MultiBlocProvider 사용함.
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
)
5) BlocListener
BlocListener는 BlocWidgetListener와 선택적 Bloc을 취하고 블록의 상태 변경에 대한 응답으로 리스너를 호출하는 Flutter 위젯이다. 네비게이션, 스낵바, 다이얼로그 띄우기 등과 같이 상태 변경당 한 번 발생해야 하는 기능에 사용해야 한다.
리스너는 BlocBuilder의 builder와 달리 각 상태 변경에 대해 한 번만 호출되고(초기 상태는 포함하지 않음) void 함수다.
bloc 매개변수가 빠져있다면 BlocBuilder는 자동으로 BlocProvider와 현재의 BuildContext를 사용해 Lookup을 수행한다
*BlocBuilder와 비슷함..
리스너 함수가 선택적으로 호출되는 시점에 대한 세밀한 제어를 위해 listenWhen을 제공할 수 있습니다. listenWhen은 이전 블록 상태와 현재 블록 상태를 가져와서 부울 값을 반환합니다. listenWhen이 true를 반환하면 리스너가 상태와 함께 호출됩니다. listenWhen이 false를 반환하면 리스너는 상태로 호출되지 않습니다.
BlocListener<BlocA, BlocAState>(
// listenWhen: (previousState, state) {
// return true/false to determine whether or not
// to call listener with state
// },
//BlocProvider와 현재 BuildContext를 통해 액세스할 수 없는 bloc을 제공하려는 경우에만 bloc 지정
//bloc: blocA,
listener: (context, state) {
// BlocA의 상태를 기반으로 여기에서 작업을 수행
},
child: Container(),
)
6) MultiBlocListener
* MultiBlocProvider와 비슷하다고 보면됨
//BlocListener<BlocA, BlocAState>(
// listener: (context, state) {},
// child: BlocListener<BlocB, BlocBState>(
// listener: (context, state) {},
// child: BlocListener<BlocC, BlocCState>(
// listener: (context, state) {},
// child: ChildA(),
// ),
// ),
//)
MultiBlocListener(
listeners: [
BlocListener<BlocA, BlocAState>(
listener: (context, state) {},
),
BlocListener<BlocB, BlocBState>(
listener: (context, state) {},
),
BlocListener<BlocC, BlocCState>(
listener: (context, state) {},
),
],
child: ChildA(),
)
7) BlocConsumer
BlocConsumer는 새로운 state에 반응하기 위해 빌더와 리스너를 노출한다. BlocConsumer는 중첩된 BlocListener 및 BlocBuilder와 유사하지만 필요한 보일러플레이트의 양을 줄인다. BlocConsumer는 UI를 다시 빌드하고 bloc 의 상태 변경에 대한 다른 반응을 실행해야 할 때만 사용해야 한다. BlocConsumer는 필수 BlocWidgetBuilder 및 BlocWidgetListener와 선택적 블록인 BlocBuilderCondition 및 BlocListenerCondition을 사용한다.
bloc 매개변수가 빠져있다면 BlocBuilder는 자동으로 BlocProvider와 현재의 BuildContext를 사용해 Lookup을 수행한다
또한 리스너와 빌더가 호출되는 시점을 보다 세부적으로 제어하기 위해 선택적인 listenWhen 및 buildWhen를 구현할 수 있다. 각 bloc 상태가 변경될 때마다 listenWhen 및 buildWhen가 호출된다.
BlocConsumer가 초기화되면 이전 state는 bloc의 state로 초기화됩니다. listenWhen 및 buildWhen는 선택 사항이며 구현되지 않은 경우 기본적으로 true로 설정됩니다.
BlocConsumer<BlocA, BlocAState>(
//listenWhen: (previous, current) {
// return true/false to determine whether or not
// to invoke listener with state
//},
listener: (context, state) {
// do stuff here based on BlocA's state
},
//buildWhen: (previous, current) {
// return true/false to determine whether or not
// to rebuild the widget with state
//},
builder: (context, state) {
// return widget here based on BlocA's state
}
)
8) RepositoryProvider
RepositoryProvider는 RepositoryProvider.of<T>(context)를 통해 자식에게 저장소를 제공하는 Flutter 위젯이다. 종속성 주입(DI) 위젯으로 사용되므로 저장소의 단일 인스턴스가 하위 트리 내의 여러 위젯에 제공될 수 있다. BlocProvider는 블록을 제공하는 데 사용해야 하지만 RepositoryProvider는 저장소에만 사용해야 한다.
RepositoryProvider(
create: (context) => RepositoryA(),
child: ChildA(),
);
//그런 다음 ChildA에서 다음을 사용하여 Repository 인스턴스를 검색
// with extensions
context.read<RepositoryA>();
// without extensions
RepositoryProvider.of<RepositoryA>(context)
9) MultiRepositoryProvider
복수의 RepositoryProvider를 사용하기 위한 위젯
//RepositoryProvider<RepositoryA>(
// create: (context) => RepositoryA(),
// child: RepositoryProvider<RepositoryB>(
// create: (context) => RepositoryB(),
// child: RepositoryProvider<RepositoryC>(
// create: (context) => RepositoryC(),
// child: ChildA(),
// )
// )
//)
MultiRepositoryProvider(
providers: [
RepositoryProvider<RepositoryA>(
create: (context) => RepositoryA(),
),
RepositoryProvider<RepositoryB>(
create: (context) => RepositoryB(),
),
RepositoryProvider<RepositoryC>(
create: (context) => RepositoryC(),
),
],
child: ChildA(),
)
3. 결론
bloc의 구성요소를 살펴보았다.
이론만 보면 어렵다. 다음에는 예시를 통해 직접 사용되는 과정을 살펴보자.
'Mobile > Flutter' 카테고리의 다른 글
flutter ci&cd, firebase flavor (0) | 2022.09.07 |
---|---|
Flutter android - BuildConfig 사용 (0) | 2022.07.23 |
Flutter flavors 설정 (0) | 2022.07.23 |
[flutter] Bloc Usage - official document (0) | 2022.07.19 |
[flutter] Bloc 이란? - official document (0) | 2022.07.19 |
댓글