在 flutter 中使用 bloc pattern 时的建议
Recommendation when using bloc pattern in flutter
当使用 flutter bloc 时,建议是什么?是否建议每个页面都有自己的 bloc,或者我可以为多个页面重用一个块,如果可以的话如何?
对此没有硬性规定。这取决于你想要完成什么。
例如:如果每个页面彼此 "radically",那么是的,每页 BLoC
是有意义的。如果页面之间需要某种共享或交互,您仍然可以在这些页面之间共享 "application-wide" BLoC
。
总的来说,我注意到 BLoC
"per page" 通常很有用,因为您在其 BLoC
中处理的每个页面总是有相关的特定内容。您可以使用通用 BLoC
在它们之间共享数据或其他一些常见的东西。
您可以将 BLoC
模式与 RxDart 结合使用,以处理 BLoC
和 UI 之间更复杂的交互场景。
共享 BLoC
相当简单,只需将它们嵌套或使用 MultiProvider
(来自 provider package):
runApp(
BlocProvider(
builder: (_) => SettingsBloc(),
child: BlocProvider(
builder: (_) => ApplicationBloc(),
child: MyApp()
)
)
);
然后您可以通过 Provider
:
检索它们
class MyApp extends ... {
@override
Widget build(BuildContext context) {
final settingsBloc = Provider.of<SettingsBloc>(context);
final appBloc = Provider.of<ApplicationBloc>(context);
// do something with the above BLoCs
}
}
您可以使用 BlocProvider 在不同的页面中共享不同的 bloc。
让我们定义一些 RootWidget 来负责保存所有 Bloc。
class RootPage extends StatefulWidget {
@override
_RootPageState createState() => _RootPageState();
}
class _RootPageState extends State<RootPage> {
NavigationBloc _navigationBloc;
ProfileBloc _profileBloc;
ThingBloc _thingBloc;
@override
void initState(){
_navigationBloc = NavigationBloc();
_thingBloc = ThingBloc();
_profileBloc = ProfileBloc();
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<NavigationBloc>(
builder: (BuildContext context) => _navigationBloc
),
BlocProvider<ProfileBloc>(
builder: (BuildContext context) => _profileBloc
),
BlocProvider<ThingBloc>(
builder: (BuildContext context) => _thingBloc
),
],
child: BlocBuilder(
bloc: _navigationBloc,
builder: (context, state){
if (state is DrawProfilePage){
return ProfilePage();
} else if (state is DrawThingsPage){
return ThingsPage();
} else {
return null
}
}
)
)
}
}
之后,我们可以使用来自父级的任何 bloc,所有小部件将共享相同的状态,并且可以在同一个 bloc 上调度事件
class ThingsPage extends StatefulWidget {
@override
_ThingsPageState createState() => _ThingsPageState();
}
class _ThingsPageState extends State<ThingsPage> {
@override
void initState(){
_profileBloc = BlocProvider.of<ProfileBloc>(context);
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: BlocBuilder(
bloc: _profileBloc,
builder: (context, state){
if (state is ThingsAreUpdated){
return Container(
Text(state.count.toList())
);
} else {
return Container()
}
}
)
);
}
}
我认为最好的解决方案是每页有一个 BLoC。通过查看其 BLoC,它可以帮助您始终了解每个屏幕处于哪种状态。如果您想独立显示每个选项卡的状态,您应该为每个选项卡创建一个 BLoC,并创建一个将处理数据获取的存储库。但是,如果每个选项卡的状态都相同(例如,您只为所有屏幕获取一次数据,所以您不会在每个选项卡上显示加载屏幕)那么我认为您可以只为所有创建一个 BLoC此选项卡的数量。
还值得补充的是,BLoC 可以相互通信。因此,您可以从一个 BLoC 获取另一个 BLoC 的状态,或监听其状态变化。当您决定为选项卡创建单独的 BLoC 时,这可能会有所帮助。
我已经在 latest article 中讨论了这个主题。如果您想深入了解,可以查看一下。
当使用 flutter bloc 时,建议是什么?是否建议每个页面都有自己的 bloc,或者我可以为多个页面重用一个块,如果可以的话如何?
对此没有硬性规定。这取决于你想要完成什么。
例如:如果每个页面彼此 "radically",那么是的,每页 BLoC
是有意义的。如果页面之间需要某种共享或交互,您仍然可以在这些页面之间共享 "application-wide" BLoC
。
总的来说,我注意到 BLoC
"per page" 通常很有用,因为您在其 BLoC
中处理的每个页面总是有相关的特定内容。您可以使用通用 BLoC
在它们之间共享数据或其他一些常见的东西。
您可以将 BLoC
模式与 RxDart 结合使用,以处理 BLoC
和 UI 之间更复杂的交互场景。
共享 BLoC
相当简单,只需将它们嵌套或使用 MultiProvider
(来自 provider package):
runApp(
BlocProvider(
builder: (_) => SettingsBloc(),
child: BlocProvider(
builder: (_) => ApplicationBloc(),
child: MyApp()
)
)
);
然后您可以通过 Provider
:
class MyApp extends ... {
@override
Widget build(BuildContext context) {
final settingsBloc = Provider.of<SettingsBloc>(context);
final appBloc = Provider.of<ApplicationBloc>(context);
// do something with the above BLoCs
}
}
您可以使用 BlocProvider 在不同的页面中共享不同的 bloc。
让我们定义一些 RootWidget 来负责保存所有 Bloc。
class RootPage extends StatefulWidget {
@override
_RootPageState createState() => _RootPageState();
}
class _RootPageState extends State<RootPage> {
NavigationBloc _navigationBloc;
ProfileBloc _profileBloc;
ThingBloc _thingBloc;
@override
void initState(){
_navigationBloc = NavigationBloc();
_thingBloc = ThingBloc();
_profileBloc = ProfileBloc();
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<NavigationBloc>(
builder: (BuildContext context) => _navigationBloc
),
BlocProvider<ProfileBloc>(
builder: (BuildContext context) => _profileBloc
),
BlocProvider<ThingBloc>(
builder: (BuildContext context) => _thingBloc
),
],
child: BlocBuilder(
bloc: _navigationBloc,
builder: (context, state){
if (state is DrawProfilePage){
return ProfilePage();
} else if (state is DrawThingsPage){
return ThingsPage();
} else {
return null
}
}
)
)
}
}
之后,我们可以使用来自父级的任何 bloc,所有小部件将共享相同的状态,并且可以在同一个 bloc 上调度事件
class ThingsPage extends StatefulWidget {
@override
_ThingsPageState createState() => _ThingsPageState();
}
class _ThingsPageState extends State<ThingsPage> {
@override
void initState(){
_profileBloc = BlocProvider.of<ProfileBloc>(context);
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: BlocBuilder(
bloc: _profileBloc,
builder: (context, state){
if (state is ThingsAreUpdated){
return Container(
Text(state.count.toList())
);
} else {
return Container()
}
}
)
);
}
}
我认为最好的解决方案是每页有一个 BLoC。通过查看其 BLoC,它可以帮助您始终了解每个屏幕处于哪种状态。如果您想独立显示每个选项卡的状态,您应该为每个选项卡创建一个 BLoC,并创建一个将处理数据获取的存储库。但是,如果每个选项卡的状态都相同(例如,您只为所有屏幕获取一次数据,所以您不会在每个选项卡上显示加载屏幕)那么我认为您可以只为所有创建一个 BLoC此选项卡的数量。
还值得补充的是,BLoC 可以相互通信。因此,您可以从一个 BLoC 获取另一个 BLoC 的状态,或监听其状态变化。当您决定为选项卡创建单独的 BLoC 时,这可能会有所帮助。
我已经在 latest article 中讨论了这个主题。如果您想深入了解,可以查看一下。