导航到另一个 pageView 或任何 View 时,Bloc 小部件 reftech 数据(重建)
Posted
技术标签:
【中文标题】导航到另一个 pageView 或任何 View 时,Bloc 小部件 reftech 数据(重建)【英文标题】:Bloc widgets reftech data (rebuild) when navigating to another pageView or any View altogether 【发布时间】:2020-09-27 22:13:24 【问题描述】:上下文:我有一个应用程序,它有一个 PageView
使用 BottomNavigationBar
在五个屏幕之间导航,一个页面正在使用 Bloc 模式(几乎所有页面都将使用 Bloc在未来的版本中)这些 Bloc 正在从后端服务获取数据,以使用获取的数据填充 UI。
问题:在小部件树的任何级别的页面之间导航时。 Bloc 小部件“重置”并从存储库中重新获取数据。
如下图所示:
Widget 树如下:
main.dart home.dart timeline.dart(屏幕截图所示)尝试过的解决方案:我将AutomaticKeepAliveClientMixin
添加到页面类和其他页面,但它没有完成这项工作。
这是上面屏幕截图中显示的页面的构建方法的代码
@override
Widget build(BuildContext context)
super.build(context);
return DefaultTabController(
length: 4,
child: Scaffold(
backgroundColor: Colors.white,
appBar: _builAppBarWithTabs(),
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 1200),
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 150),
child: Container(
height: 800,
child: CustomScrollView(
scrollDirection: Axis.vertical,
slivers: <Widget>[
SliverToBoxAdapter(
child: MasonryGrid(
column: getResponsiveColumnNumber(context, 1, 2, 6),
children: <Widget>[
// First Bloc
BlocProvider(
create: (context)
BrandBloc(repository: _brandRepository);
,
child: Container(
width: 200,
alignment: Alignment.center,
height: 80,
child: BrandScreen(
brandBloc: context.bloc(),
),
),
),
CategoryScreen(
// Second Bloc
categoryBloc: CategoryBloc(
repository: context.repository(),
),
),
Container(
width: 200,
alignment: Alignment.center,
height: 330,
child: _buildFeaturedItemsList(),
),
Placeholder(
strokeWidth: 0,
color: Colors.white,
)
],
),
),
],
),
),
),
],
),
),
),
),
);
here 是类timeline.dart
的代码
here 是包含BottomNavigationBar
类的home.dart
类的代码
问题:如何在每次小部件重建时阻止块获取数据?
【问题讨论】:
【参考方案1】:我终于明白了这个问题
事实证明,这与bloc
无关,而是与PageView
有关的问题。
我用PageStorage
小部件包装了PageView
,如下所示:
final PageStorageBucket bucket = PageStorageBucket(); //PageStorageBucket
static List<Widget> pages = [
Timeline(pageController: pageController, key: PageStorageKey('timeline')),
Search(key: PageStorageKey('search')),
LikeScreen(key: PageStorageKey('like')),
CartScreen(key: PageStorageKey('cart')),
storageService.getFromDisk('api_token') != null
? ProfileScreen(key: PageStorageKey('profile'))
: AuthChooserScreen(key: PageStorageKey('auth')),
];
@override
Widget build(BuildContext context)
super.build(context);
return SafeArea(
top: true,
bottom: true,
child: Scaffold(
backgroundColor: Colors.white,
key: _scaffoldKey,
//Wrapped PageView with PageStorage
body: PageStorage(
bucket: bucket,
child: PageView(
children: pages,
controller: pageController,
onPageChanged: onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
),
bottomNavigationBar: _buildBottomNavigationBar(),
),
);
每个页面都分配有一个 PageStorageKey,用于保存和恢复比小部件寿命更长的值
感谢这篇出色的媒体文章完美地解释了它: Keeping State with the Bottom Navigation Bar in Flutter
【讨论】:
【参考方案2】:您以错误的方式使用 BlocProvider 小部件 相反,您应该将 BlocProvider 提取到在页面之间导航时不会重新构建的上层“如果您在整个应用程序中使用此块,则可能是 MaterialApp 小部件”。 然后使用 BlocBuilder 或 BlocConsumer 将现有的 Bloc 实例提供给子小部件,并在 bloc 状态更改时自动重建。 BlocBuilder 官方文档: https://bloclibrary.dev/#/flutterbloccoreconcepts?id=blocbuilder
【讨论】:
以上是关于导航到另一个 pageView 或任何 View 时,Bloc 小部件 reftech 数据(重建)的主要内容,如果未能解决你的问题,请参考以下文章