导航到另一个 pageView 或任何 View 时,Bloc 小部件 reftech 数据(重建)

Bloc widgets reftech data (rebuild) when navigating to another pageView or any View altogether

上下文: 我有一个应用 PageView 使用 BottomNavigationBar 在五个屏幕之间导航,一个页面正在使用 Bloc 模式(在未来的版本中,几乎所有页面都将使用 Bloc)这些 Bloc 正在从后端服务获取数据,并用获取的数据填充 UI。

问题: 在小部件树的任何级别的页面之间导航时。 Bloc 小部件 'reset' 并从存储库重新获取数据。

如下图所示:

Widget树如下:

尝试过的解决方案: 我将 AutomaticKeepAliveClientMixin 添加到页面 class 和其他页面,但它没有完成工作。

以上截图所示页面的构建方法代码如下

   @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 是 class timeline.dart

的代码

here 是 class home.dart 的代码,其中包含 BottomNavigationBar class

问题:如何在每次重建小部件时阻止块获取数据?

您以错误的方式使用了 BlocProvider 小部件 相反,您应该将 BlocProvider 提取到在页面之间导航时不重建的上层 "maby to MaterialApp widget if you are using this bloc across your app"。 然后使用 BlocBuilder 或 BlocConsumer 为子部件提供现有的 Bloc 实例,并在 bloc 状态更改时自动重建。 BlocBuilder 官方文档: https://bloclibrary.dev/#/flutterbloccoreconcepts?id=blocbuilder

我终于明白了这个问题 事实证明,这与 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