Flutter使用Flutter Modular切换底部导航栏时如何保留页面状态
问题根因
当前状态重置的核心原因是Modular.to.navigate方法会替换RouterOutlet内的当前路由实例,旧路由页面会被直接从Widget树移除销毁,即便用静态变量存储页面实例,重新挂载时依然会重置内部状态。
可行解决方案
方案1:修改Modular路由逻辑+保活配置
首先给所有标签子路由配置静态单例,同时给每个标签页混入保活Mixin:
// 路由模块内预定义所有标签页的静态实例 static const HomePage homepage = HomePage(); static const FavoritesPage favoritesPage = FavoritesPage(); static const NewListingPage newListingPage = NewListingPage(); static const MessagesPage messagesPage = MessagesPage(); static const ProfilePage profilePage = ProfilePage(); @override final List<ModularRoute> routes = [ ChildRoute('/home', child: (context, args) => MainPage(), transition: TransitionType.scale, guards: [AuthGuard(authModel: authModel, guardedRoute: '/login')], children: [ ChildRoute('/', child: (_, __) => homepage, transition: TransitionType.fadeIn), ChildRoute('/favorites', child: (_, __) => favoritesPage, transition: TransitionType.fadeIn), ChildRoute('/new-listing', child: (_, __) => newListingPage, transition: TransitionType.fadeIn), ChildRoute('/messages', child: (_, __) => messagesPage, transition: TransitionType.fadeIn), ChildRoute('/profile', child: (_, __) => profilePage, transition: TransitionType.fadeIn), ], ) ];
每个标签页的State都添加保活Mixin:
class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); // 原有页面代码 } }
方案2:改用IndexedStack承载标签页(更稳定性能更好)
完全避开Modular路由的销毁逻辑,直接在MainPage内缓存所有页面实例,切换时仅修改显示索引,不会销毁任何页面:
// 预定义所有标签页实例 final List<Widget> _tabPages = const [ HomePage(), FavoritesPage(), NewListingPage(), MessagesPage(), ProfilePage(), ]; int _selectedPageIndex = 0; void _changePageIndex(int id) { if (id != _selectedPageIndex) { setState(() { _selectedPageIndex = id; }); // 如需同步路由地址可保留以下代码,不影响页面状态 switch(id) { case 0: Modular.to.navigate('/home/'); break; case 1: Modular.to.navigate('/home/favorites'); break; case 2: Modular.to.navigate('/home/new-listing'); break; case 3: Modular.to.navigate('/home/messages'); break; case 4: Modular.to.navigate('/home/profile'); break; } } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( // 替换原有RouterOutlet为IndexedStack child: IndexedStack( index: _selectedPageIndex, children: _tabPages, ), ), // 原有底部导航栏代码保持不变 bottomNavigationBar: // 原有代码 ); }
同样需要给所有标签页混入AutomaticKeepAliveClientMixin,即可完美保留滚动位置、表单输入等所有状态。
内容的提问来源于stack exchange,提问作者Arinton Akos
相关产品推荐
相关产品推荐

