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

使用PageRouteBuilder时避免Flutter页面重建的问题

解决PageRouteBuilder页面重复重建与过渡显示初始页面问题

核心问题分析

  1. 你当前每次调用RouteChange时,大概率是每次都传入新创建的exitPage/enterPage实例,导致页面被强制重建。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 23:20:27