BottomNavigationBar 页面更改导致 StreamBuilder 数据重新加载

Posted

技术标签:

【中文标题】BottomNavigationBar 页面更改导致 StreamBuilder 数据重新加载【英文标题】:BottomNavigationBar page change causing StreamBuilder data reload 【发布时间】:2019-05-09 23:46:01 【问题描述】:

BottomNavigation 里面我有 2 页。第一页从网络加载数据并显示在 SliverList 中,另一页显示静态列表数据。

从第 1 页移动到第 2 页后,第 1 页所有网络数据都消失了。我已经使用了 PageStorageKey 但仍然无法正常工作。但第二页从未重新加载。

为什么第一个页面没有保存其具有 StreamBuilder 的状态?

我的代码:

底部导航页面:

class MainActivity extends StatefulWidget 
  @override
  _MainActivityState createState() => _MainActivityState();


class _MainActivityState extends State<MainActivity> 

  final Key keyHome = PageStorageKey('pageHome');
  final Key keyChat = PageStorageKey('pageChat');

  int currentTab = 0;

  HomePage home;
  Chat chat;
  List<Widget> pages;
  Widget currentPage;

  final PageStorageBucket bucket = PageStorageBucket();
  @override
  void initState()
    home = HomePage(

      key: keyHome,
    );
    chat = Chat(
      key: keyChat,
    );
    pages = [home, chat];
    currentPage = home;

    super.initState();
  



  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: PageStorage(
        child: currentPage,
        bucket: bucket,),
      //Bottom Navigation Bar added
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: currentTab,
        onTap: (int index)
          setState(() 
            currentTab = index;
            currentPage = pages[index];
          );
        ,
        type: BottomNavigationBarType.fixed,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
          BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('Chat')),
          BottomNavigationBarItem(
              icon: Icon(Icons.payment), title: Text('Pay')),
          BottomNavigationBarItem(
              icon: Icon(Icons.account_circle), title: Text('Me')),
        ],
        //currentIndex: _selectedIndex,
        fixedColor: Colors.deepPurple,
      ),
    );
  

主页:

类 HomePage 扩展 StatefulWidget 主页( 钥匙钥匙, ) : 超级(键:键); @覆盖 _HomePageState createState() => _HomePageState();

class _HomePageState extends State<HomePage>
  @override
  Widget build(BuildContext context) 

    final NewsCatalogBlog newsBloc = BlocProvider.of<NewsCatalogBlog>(context);

    //bloc.fetchAllNews();
    return Scaffold(
      appBar: PreferredSize(child: HomePageGradientAppBar(),
        preferredSize: const Size.fromHeight(100.0),),

      body: StreamBuilder(
        stream: newsBloc.outNewsList,
        builder: (context, AsyncSnapshot<List<Data>> snapshot) 
          Widget newsList;

          newsList = new SliverList(
            delegate: new SliverChildBuilderDelegate((context,index)
              print("$index");
              return NewsListRow(snapshot.data, newsBloc, index);
            ,
                childCount: (snapshot.data == null ? 0 : snapshot.data.length) + 30),
          );

          return new CustomScrollView(
            slivers: <Widget>[
              SliverToBoxAdapter(child: TabPanel(),),
              SliverToBoxAdapter(child: UrlButtonPanel(),),
              SliverToBoxAdapter(child: ChatNowAd(),),
              newsList,
            ],
          );
        ,
      ),
    );
  

聊天页面:

聊天类扩展 StatelessWidget 聊天( 钥匙钥匙, ): super (key: key);

  @override
  Widget build(BuildContext context) 
    return ListView.builder(
      itemExtent: 250.0,
      itemCount: 20,
      itemBuilder: (context, index) => Container(
        padding: EdgeInsets.all(10.0),
        child: Material(
          elevation: 4.0,
          borderRadius: BorderRadius.circular(5.0),
          color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
          child: Center(
            child: Text('Mir$index'),
          ),
        ),
      ),
    );
  



【问题讨论】:

检查 -AutomaticKeepAliveClientMixin - docs.flutter.io/flutter/widgets/… 同样的结果。我的滚动位置已保存,但列表数据再次重新加载。 你需要保持你的构建方法纯粹 - 检查 remi 的好答案 - ***.com/a/52249579/10269042 我在 streambuilder 中有分页系统。如何针对bottomNavigationBar进行优化? 【参考方案1】:

更好的方法是使用 IndexedStack 而不是 PageStorage 或 AutomaticKeepAliveClientMixin。

 class _MainActivityState extends State<MainActivity> 

  int _selectedPage = 0;
  List<Widget> pageList = List<Widget>();

  @override
  void initState() 
    pageList.add(HomePage());
    pageList.add(ChatPage());
    super.initState();
  

 @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: IndexedStack(
        index: _selectedPage,
        children: pageList,
      ),
      //Bottom Navigation Bar added
      bottomNavigationBar: BottomNavigationBar(
    .....

**IndexedStack Widget 是 Stack Widget 的子类

它显示提供的孩子列表中的单个孩子。 它的大小和最大的孩子一样大。 它保持所有孩子的状态。**

【讨论】:

您能否通过导航页面更改操作详细说明您的答案? medium.com/flutter/…

以上是关于BottomNavigationBar 页面更改导致 StreamBuilder 数据重新加载的主要内容,如果未能解决你的问题,请参考以下文章

在BottomNavigationBar上更改选项卡时禁用重建页面

BottomNavigationBar-更改标签图标颜色

如何路由到页面,而不在颤动中删除 BottomNavigationBar?

Flutter底部导航栏BottomNavigationBar页面状态保持解决方案

使用 Flutter 导航和路由时如何保持 BottomNavigationBar

Flutter -------- BottomNavigationBar 界面切换