gpt4 book ai didi

flutter - 从一个标签页滑动到另一个标签页时,TabView不会保留状态

转载 作者:行者123 更新时间:2023-12-03 13:30:25 25 4
gpt4 key购买 nike

上下文:这是具有TabView的页面,可在各个选项卡之间进行导航,所有这些选项卡均使用flutter_bloc(版本6.0.1)。
问题:滑动到任何选项卡时,不会保留状态,并且正在重建整个窗口小部件树,如下面的gif所示。
PageView State not being preserved when swiping
这是build()方法:

 @override
Widget build(BuildContext context) {
super.build(context);
return DefaultTabController(
initialIndex: 0,
length: 3,
child: Scaffold(
backgroundColor: Colors.white,
appBar: _buildAppBarWithTabs(),
body: TabBarView(
children: <Widget>[
defaultViewforCategory(1), //Women
defaultViewforCategory(3), //Men
defaultViewforCategory(2), //Kids
],
),
),
);
}
这是 defaultViewforCategory()函数的实现
Widget defaultViewforCategory(int mainCategoryId) {
return PageStorage(
bucket: bucket,
key: PageStorageKey(mainCategoryId),
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: RefreshIndicator(
onRefresh: () => refreshTimeline(),
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: 90,
child: BrandScreen(
brandBloc: context.bloc(),
),
),
),
CategoryScreen(
// Second Bloc
categoryBloc: CategoryBloc(
mainCategoryId: mainCategoryId,
repository: _categoryRepository),
),

// -------------- Featured Items--------------------------
Container(
width: 200,
alignment: Alignment.center,
height: 350,
child: _buildFeaturedItemsList(mainCategoryId),
),
Placeholder(strokeWidth: 0, color: Colors.white)
],
),
),
],
),
),
),
),
],
),
),
);
}
尝试的解决方案:
1-我尝试了 AutomaticKeepAliveClientMixin,但事实证明,当使用 mixin切换到另一个页面时,此 BottomNavigationBar保留了页面的状态。
2- PageStorage不能解决问题。
问题:如何在用户每次滑动到另一个选项卡时阻止 TabView的重建?

最佳答案

如您所述,问题之一是每次显示选项卡时都会重新生成TabBarView。对于该问题,有一个开放主题here。因此,每次屏幕更改时都会创建一个新的Bloc实例。
注意因为未使用CategoryBloc传递BlocProvider,所以应手动处理该块。
一个简单的解决方案是将BlocProviderTabBarView之外的层次结构中上移-例如,build方法中的第一个组件。
注意在性能方面,这是可以的,因为在请求块时会延迟初始化BLOC。
现在,更微妙的问题是CategoryBloc的创建方式(因为具有动态构造函数)。在这里,您可以有两种解决方案:

  • 您可以将CategoryBloc修改为可被所有类别屏幕共享-在这里,我没有太多帮助,因为我没有代码。这个想法是通过mainCategoryIdevents发送emits和结果的新状态。在这种情况下,您应该将mainCategoryId转发到state中,并且在BlocBuilder上,仅当buildWhen与CategoryScreen id(在创建屏幕时可以传递)匹配时,才使用mainCategoryId参数进行构建。而且,不要忘了还使用BlocProvider子级之外的TabBarView提供CategoryBloc。
  • 将CategoryBloc创建移到TabBarView之外,并将其缓存以供进一步访问。我在下面创建了一个示例来强调这一点。
    // ...

    ///
    /// Categories blocs cache.
    ///
    Map<int, CategoryBloc> _categoriesBlocs;

    ///
    /// Creates UNIQUE instances of CategoryBloc by id.
    ///
    CategoryBloc getCategoryBlocById(int id) {
    // If you don't already have a bloc for that particular id, create a new one
    // and cache it (by saving it in the Map)
    this._categoriesBlocs.putIfAbsent(
    id,
    () => CategoryBloc(
    mainCategoryId: id,
    repository: _categoryRepository,
    ));

    // Return the cached category bloc
    return this._categoriesBlocs[id];
    }

    ///
    /// This is very important. Because we manually create the BLOCs we have
    /// to manually dispose them
    ///
    @override
    void dispose() {
    for (var bloc in this._categoriesBlocs) {
    bloc.displose();
    }
    super.dispose();
    }

    @override
    Widget build(BuildContext context) {
    super.build(context);

    return MultiBlocProvider(
    providers: [
    BlocProvider(
    create: (context) => BrandBloc(repository: _brandRepository),
    )
    ],
    child: DefaultTabController(
    initialIndex: 0,
    length: 3,
    child: Scaffold(
    backgroundColor: Colors.white,
    appBar: _buildAppBarWithTabs(),
    body: TabBarView(
    children: <Widget>[
    defaultViewforCategory(1), //Women
    defaultViewforCategory(3), //Men
    defaultViewforCategory(2), //Kids
    ],
    ),
    ),
    ),
    );
    }

    // ...

    CategoryScreen(
    // Second Bloc
    // Now, here you will get the same BLOC instance every time
    categoryBloc: getCategoryBlocById(mainCategoryId),
    ),

    // ...
  • 关于flutter - 从一个标签页滑动到另一个标签页时,TabView不会保留状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63218581/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com