演示效果
通常搭建一个主框架大概是这个样子
上代码
主页代码
整体是 IndexedStack + BottomNavigationBar 的大结构
class MainPage extends StatefulWidget {MainPage({Key key}) : super(key: key);@override_MainPageState createState() => _MainPageState();}class _MainPageState extends State<MainPage> {/// 当前索引int _currentIndex = 0;@overrideWidget build(BuildContext context) {//这里打印了主页debugPrint('MainPage');return Scaffold(body: IndexedStack(index: _currentIndex,children: <Widget>[HomePage(),//首页FindPage(),//发现MsgPage(),//消息UserPage(),//我的],),bottomNavigationBar: BottomNavigationBar(type: BottomNavigationBarType.fixed,selectedItemColor: Theme.of(context).primaryColor,unselectedItemColor: Colors.grey,showUnselectedLabels: true,currentIndex: _currentIndex,onTap: (newIndex) {if (_currentIndex != newIndex) {setState(() {_currentIndex = newIndex;});}},items: [BottomNavigationBarItem(icon: Icon(Icons.home),title: Text('首页'),),BottomNavigationBarItem(icon: Icon(Icons.explore),title: Text('发现'),),BottomNavigationBarItem(icon: Icon(Icons.email),title: Text('消息'),),BottomNavigationBarItem(icon: Icon(Icons.people),title: Text('我的'),)]),);}}
Tab 页面代码
IndexedStack 中对应的四个页面布局如下
/// 首页class HomePage extends StatefulWidget {@override_HomePageState createState() => _HomePageState();}class _HomePageState extends State<HomePage> {@overrideWidget build(BuildContext context) {debugPrint('HomePage');return Scaffold(appBar: AppBar(title: Text('首页'),),body: Center(child: Text('首页')),);}}/// 发现class FindPage extends StatefulWidget {@override_FindPageState createState() => _FindPageState();}class _FindPageState extends State<FindPage> {@overrideWidget build(BuildContext context) {debugPrint('FindPage');return Scaffold(appBar: AppBar(title: Text('发现'),),body: Center(child: Text('发现')),);}}/// 消息class MsgPage extends StatefulWidget {@override_MsgPageState createState() => _MsgPageState();}class _MsgPageState extends State<MsgPage> {@overrideWidget build(BuildContext context) {debugPrint('MsgPage');return Scaffold(appBar: AppBar(title: Text('消息'),),body: Center(child: Text('消息')),);}}///我的class UserPage extends StatefulWidget {@override_UserPageState createState() => _UserPageState();}class _UserPageState extends State<UserPage> {@overrideWidget build(BuildContext context) {debugPrint('UserPage');return Scaffold(appBar: AppBar(title: Text('我的'),),body: Center(child: Text('我的')),);}}
发现问题
看上面的代码似乎很合理,但是当我们点击【发现】 Tab 时,5 个页面都进行了 rebuild,log 日志如下

是不是有些诧异?但是仔细分析主页代码,因为点击切换 Tab 时,执行了setState({}) 那么主页必然会 rebuild,然后 4 个Tab 页面又是在 IndexedStack 中创建的,所以 4 个 Tab 页,也一起 rebuild 了
return Scaffold(body: IndexedStack(index: _currentIndex,children: <Widget>[HomePage(),//首页FindPage(),//发现MsgPage(),//消息UserPage(),//我的],),bottomNavigationBar: BottomNavigationBar(...onTap: (newIndex) {if (_currentIndex != newIndex) {setState(() {_currentIndex = newIndex;});}},items: [...]),);
解决问题
我们把 4 个 Tab 页面放到 initState 中即可
class MainPage extends StatefulWidget {MainPage({Key key}) : super(key: key);@override_MainPageState createState() => _MainPageState();}class _MainPageState extends State<MainPage> {/// 当前索引int _currentIndex = 0;/// 页面列表List pageList;@overridevoid initState() {///初始化 4 个 PagepageList = <Widget>[HomePage(), //首页FindPage(), //发现MsgPage(), //消息UserPage(), //我的];super.initState();}@overrideWidget build(BuildContext context) {debugPrint('MainPage');return Scaffold(body: IndexedStack(index: _currentIndex,children: pageList,),bottomNavigationBar: BottomNavigationBar(type: BottomNavigationBarType.fixed,selectedItemColor: Theme.of(context).primaryColor,unselectedItemColor: Colors.grey,showUnselectedLabels: true,currentIndex: _currentIndex,onTap: (newIndex) {if (_currentIndex != newIndex) {setState(() {_currentIndex = newIndex;});}},items: [BottomNavigationBarItem(icon: Icon(Icons.home),title: Text('首页'),),BottomNavigationBarItem(icon: Icon(Icons.explore),title: Text('发现'),),BottomNavigationBarItem(icon: Icon(Icons.email),title: Text('消息'),),BottomNavigationBarItem(icon: Icon(Icons.people),title: Text('我的'),)]),);}}
最终点击 Tab 页看看效果
