You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PageView、BottomNavigationBar场景下保留页面状态避免重复请求API

解决方案

问题根因:当前实现中每次切换BottomNavigationBar索引时,旧页面会被从Widget树移除销毁,切回时重新初始化触发网络请求。

方案1:使用IndexedStack(改造成本最低)

IndexedStack会同时维护所有子Widget的状态,仅展示当前索引对应的页面,其余页面保持隐藏不销毁,适合页面数量较少的场景。
修改后的核心代码如下:

final List<Widget> _pages = const [
  Page1(key: Key("Page1"),),
  Page2(key: Key("Page2"),),
];

int _index=0;

@override
Widget build(BuildContext context) {
  return Scaffold(
    // 替换原来直接取_pages[_index]的逻辑
    body: IndexedStack(
      index: _index,
      children: _pages,
    ),
    bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        onTap: (index) => setState(() => _index = index),
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.edit_outlined,),
            label: "页面1"
          ),
          BottomNavigationBarItem(                  
            icon: Icon(Icons.edit_outlined,),
            label: "页面2"
          ),               
        ]),
  );
}

注意:该方案会在父页面初始化时一次性加载所有子页面的生命周期方法,所有页面的网络请求会在首次进入父页面时同时触发。

方案2:PageView + AutomaticKeepAliveClientMixin(懒加载,性能更好)

如果需要页面懒加载(首次进入对应页面才触发请求),适合页面数量多或者页面初始化成本高的场景,步骤如下:

  1. 给所有需要保活的页面的State类混入AutomaticKeepAliveClientMixin,重写wantKeepAlive返回true,示例:
class Page1State extends State<Page1> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true; // 开启保活

  @override
  void initState() {
    super.initState();
    // 这里的网络请求只会在页面第一次初始化时触发一次
    fetchApi();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context); // 必须调用父类方法
    // 你的页面布局代码
  }
}
  1. 父页面使用PageView承载子页面,搭配BottomNavigationBar切换:
final List<Widget> _pages = const [
  Page1(key: Key("Page1"),),
  Page2(key: Key("Page2"),),
];

late PageController _pageController;
int _index=0;

@override
void initState() {
  super.initState();
  _pageController = PageController(keepPage: true);
}

@override
void dispose() {
  _pageController.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: PageView(
      controller: _pageController,
      physics: const NeverScrollableScrollPhysics(), // 禁止左右滑动切换,可选
      children: _pages,
    ),
    bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        onTap: (index) {
          setState(() => _index = index);
          _pageController.jumpToPage(index);
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.edit_outlined,),
            label: "页面1"
          ),
          BottomNavigationBarItem(                  
            icon: Icon(Icons.edit_outlined,),
            label: "页面2"
          ),               
        ]),
  );
}

内容的提问来源于stack exchange,提问作者balu k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 07:36:05