Flutter中CupertinoTabBar代码运行正常但组件无法重建如何解决
问题原因
你遇到的不更新问题来自两个核心错误:
- 多处独立创建
Model实例:你在LoginScreen、TabBarScreen里都单独新建了Model对象,和main.dart中MultiProvider全局维护的Model实例不是同一个对象,虽然currentStep是静态属性值会同步,但后续还有缓存问题导致视图不刷新 CupertinoTabView默认缓存:CupertinoTabScaffold的tabBuilder会默认缓存对应索引的CupertinoTabView,同一个索引的TabView只会执行一次build逻辑,即使外层Consumer收到更新通知,也不会触发TabView内容重建
修复步骤
- 删掉所有自定义创建的
Model实例,全部使用Provider全局提供的实例 - 给动态切换的
CupertinoTabView添加唯一key,触发状态变更时的强制重建 - 移除冗余的
setState调用,Provider的notifyListeners已经可以触发Consumer重建
具体修改代码
1. 修改login.dart
class LoginScreen extends StatelessWidget { // 删掉自定义创建Model的代码:final model = Model(); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('app',), ), child: Container( alignment: FractionalOffset.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ElevatedButton( child: Text('next'), onPressed: (){ // 改用Provider提供的全局实例修改状态 Provider.of<Model>(context, listen: false).setStep('step1'); Navigator.pushNamed(context, '/tab_bar'); }, style: ElevatedButton.styleFrom( primary: CupertinoColors.white, side: BorderSide(color: Colors.blue, width: 2.0) ), ), ] ), ), ); } }
2. 修改tab_bar.dart
class TabBarScreenState extends State<TabBarScreen> { // 删掉自定义创建Model的代码:final model = Model(); @override void initState() { super.initState(); } @override Widget build(BuildContext context) { // 删掉冗余打印:print(model.getStep); return Consumer<Model>( builder: (context, model, _) => CupertinoTabScaffold( tabBar: CupertinoTabBar( backgroundColor: CupertinoColors.white, inactiveColor: Colors.blue, activeColor: Colors.blueAccent, border: const Border( top: BorderSide( color: CupertinoColors.activeBlue, width: 2.0, ), ), items: <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.favorite_outline_outlined), ), BottomNavigationBarItem( icon: Icon(Icons.more_vert_sharp), ), ], ), tabBuilder: (context, index) { late final CupertinoTabView returnValue; switch (index) { case 0: if (model.getStep == 'step1') { print('step1'); returnValue = CupertinoTabView( // 添加唯一key,step变化时触发TabView重建 key: ValueKey(model.getStep), builder: (context) { return CupertinoPageScaffold( child: SafeArea( child: GestureDetector( onTap: (){ }, child: Column( children: <Widget>[ Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Container( margin: const EdgeInsets.only(bottom: 15.0), child: FloatingActionButton( onPressed: () { model.setStep('step2'); // 删掉冗余的setState调用 }, tooltip: 'step2', child: Icon(Icons.add), backgroundColor: CupertinoColors.white, foregroundColor: CupertinoColors.black, ), ), ], ), ], ), ), ), ); }); } else if (model.getStep == 'step2') { print('step2'); returnValue = CupertinoTabView( // 同样添加唯一key key: ValueKey(model.getStep), builder: (context) { return CupertinoPageScaffold( child: SafeArea( child: Column( children: <Widget> [ Text('step2'), ], ), ), ); }); } else { returnValue = CupertinoTabView(builder: (context) { return Container(); }); } break; case 1: returnValue = CupertinoTabView(builder: (context) { return CupertinoPageScaffold( child: Text("Tab2"), ); }); break; } return returnValue; }, ), ); } }
修改完成后点击按钮即可正常切换step1和step2的视图。
内容的提问来源于stack exchange,提问作者discodancer
相关产品推荐
相关产品推荐

