BLOC
Bussiness Logic Component
비즈니스 로직과 ui를 구분 짓고 필요에 따라 원하는 부분만 데이터 처리
실 사용 예제
버튼 클릭시 증감
1. Stateful version
ui widget - 버튼 클릭시 증감
//stateless widget으로 count를 보내 화면에 그려줌
body: CountViewStateless(count: count),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
count++;
});
},
),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
count--;
});
},
),
],
),
view - 결과 출력
import 'package:flutter/material.dart';
class CountViewStateless extends StatelessWidget {
int count;
CountViewStateless({Key key, this.count}) : super(key: key);
@override
Widget build(BuildContext context) {
print("CountViewStateless Build !!");
return Center(
child: Text(
count.toString(),
style: TextStyle(fontSize: 80),
));
}
}
2. bloc pattern
ui widget - 값을 변경시키는 이벤트 발생
// 전역변수로 bloc 생성
CountBloc countBloc;
class _BlocDisplayWidgetState extends State<BlocDisplayWidget> {
@override
void initState() {
super.initState();
// bloc
countBloc = CountBloc();
}
@override
void dispose() {
super.dispose();
// bloc 종료
countBloc.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("bloc 패턴"),
),
body: CountView(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
// add는 이벤트를 등록한다는 의미
// 숫자를 더하거나 빼는 로직이 현재파일에는 존재하지 않음
countBloc.countEventBloc.countEventSink.add(CountEvent.ADD_EVENT);
},
),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
countBloc.countEventBloc.countEventSink
.add(CountEvent.SUBTRACT_EVENT);
},
),
],
),
);
}
}
count_bloc - 비즈니스 로직 처리
import 'dart:async';
//bloc
class CountBloc {
CountEventBloc countEventBloc = CountEventBloc();
int _count = 0;
// broadcast를 넣어주면 여러군데에서 구독 가능
final StreamController<int> _countSubject = StreamController<int>.broadcast();
// count는 _countSubject.stream를 구독하고 있는 모든 widget에게 변경된 상태값을 전달
Stream<int> get count => _countSubject.stream;
// 생성자
CountBloc() {
// countEventBloc의 _countEventSubject을 구독
countEventBloc._countEventSubject.stream.listen(_countEventListen);
}
// 생성자에서 변화를 감지하여 listen으로 리턴 받은 것
// 인자값 event에 해당하는 것은 enum에 등록된 이벤트
_countEventListen(CountEvent event) {
// 비즈니스 로직 부분
switch (event) {
case CountEvent.ADD_EVENT:
_count++;
break;
case CountEvent.SUBTRACT_EVENT:
_count--;
break;
}
// 결과값인 _count를 sink에 add로 넣어줌
_countSubject.sink.add(_count);
}
dispose() {
_countSubject.close();
countEventBloc.dispose();
}
}
// event
class CountEventBloc {
final StreamController<CountEvent> _countEventSubject =
StreamController<CountEvent>();
// event 값이 sink로 들어오면 _countEventSubject를 통해 구독자에게 알려줌
Sink<CountEvent> get countEventSink => _countEventSubject.sink;
dispose() {
_countEventSubject.close();
}
}
// event에 해당하는 enum
enum CountEvent { ADD_EVENT, SUBTRACT_EVENT }
count_view 결과값 받아오는 곳
StreamBuilder(
// stream을 리스닝
stream: countBloc.count, // Stream<int> get count => _countSubject.stream; 구독
initialData: 0,
// snapshot으로 값이 들어옴
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 80),
);
}
return CircularProgressIndicator();
},
),
3. Skip event bloc pattern
ui 위와 다르게 바로 이벤트 호출함
class _BlocDisplayWidgetState extends State<BlocDisplayWidget> {
@override
void initState() {
super.initState();
countBloc = CountBloc();
}
@override
void dispose() {
super.dispose();
countBloc.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("bloc 패턴"),
),
body: CountView(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
// 이벤트 호출
countBloc.add();
},
),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
countBloc.subtract();
},
),
],
),
);
}
}
count_bloc - skip event 비즈니스 로직 처리
import 'dart:async';
class CountBloc {
int _count = 0;
final StreamController<int> _countSubject = StreamController<int>.broadcast();
Stream<int> get count => _countSubject.stream;
add() {
_count++;
_countSubject.sink.add(_count);
}
subtract() {
_count--;
_countSubject.sink.add(_count);
}
dispose() {
_countSubject.close();
}
}
참고
https://www.youtube.com/watch?v=AY6i0a4BM7o
'Usage > Flutter' 카테고리의 다른 글
[Flutter] GetX 단순 상태관리, Provider 비교 (0) | 2021.06.17 |
---|---|
[Flutter] GetX Routing 사용법 및 기존 routing 비교 (0) | 2021.06.17 |
[Flutter] FutureBuilder를 통해 future 리턴 받기 (0) | 2021.06.15 |
[Flutter] TextField안의 상단에 prefix 넣기 (0) | 2021.06.11 |
[Flutter] 키보드 높이 만큼 페이지 이동(동적스크롤링) (0) | 2021.06.11 |