使用PageRouteBuilder时避免Flutter页面重建的问题
解决PageRouteBuilder页面重复重建与过渡显示初始页面问题
核心问题分析
- 你当前每次调用
RouteChange时,大概率是每次都传入新创建的exitPage/enterPage实例,导致页面被强制重建。 keepAlive未生效是因为它需要作用在页面的State层,而非路由类中。
解决方案
1. 缓存页面实例,避免重复创建
不要在跳转时临时new页面,而是在父页面中提前缓存需要保活的页面实例:
// 在需要跳转的父页面中缓存实例 final _homePage = const HomePage(); // 你的exitPage对应的页面 final _detailPage = const DetailPage(); // 你的enterPage对应的页面 // 跳转时直接传入缓存的实例 Navigator.push(context, RouteChange( exitPage: _homePage, enterPage: _detailPage, beginOffsetExit: const Offset(0.0, 0.0), endOffsetExit: const Offset(0.0, -1.0), beginOffsetEnter: const Offset(0.0, 1.0), endOffsetEnter: const Offset(0.0, 0.0), beginOffsetButton: const Offset(-0.215, 0.4), endOffsetButton: const Offset(-0.215, -0.45), animatedWidget: const YourAnimatedButton(), ));
2. 给页面添加保活能力
让需要保活的页面继承AutomaticKeepAliveClientMixin,确保页面状态不被销毁:
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin { // 返回true开启保活 @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { // 必须调用super.build,否则保活不生效 super.build(context); return Scaffold( // 你的页面内容 body: ..., ); } }
3. 优化RouteChange的过渡逻辑(可选)
当前transitionsBuilder中重复使用enterPage,可以直接用参数里的child(即pageBuilder返回的页面)替代,减少冗余:
transitionsBuilder: ( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child, // 这里的child就是pageBuilder返回的enterPage ) { return Stack( children: <Widget>[ SlideTransition( position: Tween<Offset>( begin: beginOffsetExit, end: endOffsetExit, ).animate( CurvedAnimation( parent: animation, curve: Curves.linearToEaseOut, reverseCurve: Curves.easeInToLinear, ), ), child: exitPage, ), // 直接使用child替代enterPage SlideTransition( position: Tween<Offset>( begin: beginOffsetEnter, end: endOffsetEnter, ).animate( CurvedAnimation( parent: animation, curve: Curves.linearToEaseOut, reverseCurve: Curves.easeInToLinear, ), ), child: child, ), SlideTransition( position: Tween<Offset>( begin: beginOffsetButton, end: endOffsetButton ) .animate( CurvedAnimation( parent: animation, curve: Curves.linearToEaseOut, reverseCurve: Curves.easeInToLinear, ), ), child: animatedWidget, ) ], ); },
关键注意点
- 必须确保传入
RouteChange的exitPage和enterPage是同一个实例,而非每次跳转都创建新对象。 AutomaticKeepAliveClientMixin必须配合super.build(context)使用,否则保活逻辑不会生效。
内容的提问来源于stack exchange,提问作者praphi
相关产品推荐
相关产品推荐

