flutter_bloc 홈페이지 가보니 새로운 내용이 업데이트 되어 있길래 팔로우업 한다.
네비게이터를 태울때 블록을 어떻게 내려주면 좋을지 고민이 많았다. 왜냐하면 블록을 새로 만들면 상태공유가 안되기 때문에,어떻게 할지 고민이 있었는데
이 문서를 대강 훑었는데 그 내용이 상세히 설명되어있는것 같고 새로운 업데이트가 반가운 마음에 작성한다!
상단에서 내려주는 일반적인 방법
네비게이터 푸시, 팝이 없는 엑세스
상태 내려주기
home: BlocProvider(
create: (BuildContext context) => CounterBloc(),
child: CounterPage(),
),
final counterBloc = BlocProvider.of<CounterBloc>(context);
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
counterBloc.add(CounterIncrementPressed());
},
),
body: Center(
child: CounterText(),
),
특별한점 없이 일반적으로 사용하는방법 긴 설명없이 넘어가자
class CounterText extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text('$count');
},
);
}
}
상태 내려줍니다
home: BlocProvider(
create: (BuildContext context) => CounterBloc(),
child: HomePage(),
),
리턴하는 위젯에 BlocProvider.value(value:bloc, child: widget)을 래핑해서 넘겨주면 상태 제공 가능
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute<CounterPage>(
builder: (context) {
return BlocProvider.value(
value: counterBloc,
child: CounterPage(),
);
},
),
);
하던것처럼 빌더로 상태 받아서 쓰면됨
class CounterPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter'),
),
body: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Center(
child: Text('$count'),
);
},
),
);
}
}
변수에 블록 생성자를 할당하고
상단 MaterialApp의 routes에 블록을 BlocProvider.value로 넘긴다.
생성자는 꼭 dispose해준다.
class _AppState extends State<App> {
final _counterBloc = CounterBloc();
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
routes: {
'/': (context) => BlocProvider.value(
value: _counterBloc,
child: HomePage(),
),
'/counter': (context) => BlocProvider.value(
value: _counterBloc,
child: CounterPage(),
),
},
);
}
void dispose() {
_counterBloc.close();
super.dispose();
}
}
그냥 네임드 네비게이터 태우면 됩니다.
child: ElevatedButton(
onPressed: () => Navigator.of(context).pushNamed('/counter'),
child: Text('Counter'),
),
똑같음
class CounterPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter'),
),
body: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Center(
child: Text('$count'),
);
},
),
);
}
Router를 만들고 BlocProvider를 사용하여 다양한 generated routes에 접근한다. 라우터에서 우리가 원하는 범위에서 블록을 관리할것이고, 선택적으로 라우트에게 블록에 접근 권한을 줄것이다.
라우터 생성하고 MaterialApp에 라우터 넘겨줌
class _AppState extends State<App> {
final _router = AppRouter();
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
onGenerateRoute: _router.onGenerateRoute,
);
}
void dispose() {
_router.dispose();
super.dispose();
}
}
블록 생성자로 생성해주고(디스포즈 꼭 해주고)
블록프로바이더 닷 벨류로 넘겨줌
class AppRouter {
final _counterBloc = CounterBloc();
Route onGenerateRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(
builder: (_) => BlocProvider.value(
value: _counterBloc,
child: HomePage(),
),
);
case '/counter':
return MaterialPageRoute(
builder: (_) => BlocProvider.value(
value: _counterBloc,
child: CounterPage(),
),
);
default:
return null;
}
}
void dispose() {
_counterBloc.close();
}
}
네임드 라우트 그냥 태우면 됩니다.
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.of(context).pushNamed('/counter'),
child: Text('Counter'),
),
),
쓰면 됩니다 똑같음
body: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Center(
child: Text('$count'),
);
},
),
AuthenticationBloc 또는 ThemeBloc 과 같은 경우에 유용
상태 내려줍니다
중요한점은 메터리얼앱 위에 올렸다
return BlocProvider(
create: (BuildContext context) => CounterBloc(),
child: MaterialApp(
title: 'Flutter Demo',
home: CounterPage(),
),
);
사용
class CounterText extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text('$count');
},
);
}
}
블록 접근 방법은
1. 로컬
2. 익명
3. 명명
4. 라우터
5. 전역
다섯가지 방법이 있고 기존엔 1,5를 적극적으로 사용했었다.
4번, 3번이 Navigator에 유연하게 대처할 수 있고 세련되어 보여서 리팩토링을 한번 진행해 봐야겠다.