如何使用 Provider 为 PageView() 提供一个块,而无需每次切换页面时孩子都重新订阅?
Posted
技术标签:
【中文标题】如何使用 Provider 为 PageView() 提供一个块,而无需每次切换页面时孩子都重新订阅?【英文标题】:How can I use Provider to provide a bloc to a PageView() without the child resubscribing everytime I switch page? 【发布时间】:2020-08-11 18:01:55 【问题描述】:我正在使用 Provider 通过静态创建方法将我的块提供给名为 TheGroupPage 的小部件
static Widget create(BuildContext context, GroupModel group)
final database = Provider.of<DatabaseService>(context);
return Provider(
create: (_) => GroupMembersBloc(database, group),
child: TheGroupPage(group),
dispose: (BuildContext context, GroupMembersBloc bloc) => bloc.dispose(),
);
那个小部件有一个包含 3 页的 PageView()
PageView(children: [
TheGroupNotificationsView(),
TheGroupMembersView(group),
TheGroupSettingsView(group),
])
组成员视图查找 GroupMembersBloc
GroupMembersBloc bloc = Provider.of<GroupMembersBloc>(context);
我也尝试将 listen 设置为 false,但这没有用。我希望小部件能够监听任何变化。该页面使用该 bloc 的流来绘制组成员列表
class GroupMembersBloc
StreamController<List<UserModel>> _controller = StreamController<List<UserModel>>();
Stream<List<UserModel>> get stream => _controller.stream;
GroupMembersBloc(DatabaseService database, GroupModel group)
_controller.addStream(database.groupMembersStream(group));
void dispose()
_controller.close();
问题是当我在 PageView() 内切换页面时,在页面第一次显示后出现错误。错误提示 Bad state: Stream has already been listened to.
我该如何解决?
【问题讨论】:
【参考方案1】:这是因为流控制器只允许 1 个订阅(或 1 个侦听器),您可以使用 [StreamController<List<UserModel>>.broadcast()][1]
构造函数代替 StreamController>()。
【讨论】:
是的,但我只有 1 个页面可以收听流。那么为什么要让它成为广播流呢?我会有多个不必要的听众。使用 PageView() 切换页面时没有办法停止监听吗?【参考方案2】:我最终将 StreamBuilder 移动到了解决问题的 PageView() 上方的父小部件。
【讨论】:
以上是关于如何使用 Provider 为 PageView() 提供一个块,而无需每次切换页面时孩子都重新订阅?的主要内容,如果未能解决你的问题,请参考以下文章
如何在颤动的pageView中使用AnimatedCrossFade多个小部件?