[ Flutter / 플러터 ] Bloc 패턴 왜 써야 하는가? - YouTube
1. CountBloc.dart
import "dart:async";
class CountBloc {
int _count = 0;
final StreamController<int> _countStream = StreamController<int>();
Stream<int> get count => _countStream.stream;
CountEventBloc countEventBloc = CountEventBloc();
CountBloc() {
countEventBloc._countEventStream.stream.listen((event) {
switch (event) {
case CountEvent.EVENT_PLUS:
_count++;
break;
case CountEvent.EVENT_MINUS :
_count--;
break;
}
_countStream.sink.add(_count);
});
}
dispose () {
_countStream.close();
countEventBloc.dispose();
}
}
class CountEventBloc {
final StreamController<CountEvent> _countEventStream = StreamController<CountEvent>();
Sink<CountEvent> get countEventSink => _countEventStream.sink;
dispose() {
_countEventStream.close();
}
}
enum CountEvent {EVENT_PLUS, EVENT_MINUS}
2. CountView.dart
import "package:flutter/material.dart";
import "package:bloc/CountBloc.dart";
class CountView extends StatelessWidget {
final CountBloc countBloc;
const CountView({super.key, required this.countBloc});
@override
Widget build(BuildContext context) {
print("CountView Build!!");
return Center(
child: StreamBuilder(
stream: countBloc.count,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.toString(), style: const TextStyle(fontSize: 80),);
}
return const CircularProgressIndicator();
},
),
);
}
}
3. main.dart
import "package:flutter/material.dart";
import "package:bloc/CountBloc.dart";
import "package:bloc/CountView.dart";
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Bloc Sample",
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const BlocMain(title: "Bloc Main Page"),
);
}
}
class BlocMain extends StatefulWidget {
const BlocMain({super.key, required this.title});
final String title;
@override
State<BlocMain> createState() => _BlocMain();
}
class _BlocMain extends State<BlocMain> {
late final CountBloc countBloc;
@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(widget.title)),
body: CountView(countBloc: countBloc),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(onPressed: () {
countBloc.countEventBloc.countEventSink.add(CountEvent.EVENT_PLUS);
}, icon: const Icon(Icons.add)),
IconButton(onPressed: () {
countBloc.countEventBloc.countEventSink.add(CountEvent.EVENT_MINUS);
}, icon: const Icon(Icons.remove))
],
),
);
}
}
카운트위젯생성시 한번만 build가 호출되고, count 더하기, 빼기 시에는 호출되지 않는다.
위와 같은 Bloc구조는 관리해야할 파일이 많아지므로
CountEventBloc를 생략하고
CountBloc Class에 plus, minus Method를 만들어 바로 count를 + - 하여 _countStream.sink.add(_count);호출 하도록 만들고
UI에서는 countBloc.plus() 혹은 countBloc.minus()로 바로 이벤트 없이 호출하여 단순화 시킬수 도 있다.