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

AutoRouter BottomNavigationBar重复渲染及页面多次Build问题的修复咨询

AutoRouter BottomNavigationBar重复渲染及页面多次Build问题的修复咨询

看起来你在使用AutoRouter开发Flutter应用时,碰到了底部导航栏重复绘制、部分页面多次触发build方法的问题,结合你给出的代码和修复方案,我来帮你梳理下问题根因和解决思路:

问题根因分析

从你提供的原始路由配置(app_router.dart)可以看到,RootRoute作为HomeRoute的子路由,同时自身还嵌套了DictionaryRoute和OwnDictionaryRoute两个子路由:

// 原始问题路由配置
part 'app_router.gr.dart';

/// [AppRouter] is the router of the app
@AutoRouterConfig(replaceInRouteName: AppRouter._replaceInRouteName)
final class AppRouter extends _$AppRouter {
  static const _replaceInRouteName = 'View,Route';

  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          page: HomeRoute.page,
          initial: true,
          children: [
            AutoRoute(
              page: RootRoute.page,
              children: [
                AutoRoute(page: DictionaryRoute.page),
                AutoRoute(page: OwnDictionaryRoute.page),
              ],
            ),
          ],
        ),
        AutoRoute(page: OTPRoute.page),
        AutoRoute(page: PhoneNumberVerificationRoute.page),
        AutoRoute(page: SignUpRoute.page),
      ];
}

而RootView中使用了AutoTabsScaffold来管理底部导航,这种路由嵌套+AutoTabsScaffold路由容器的组合,会导致路由被重复加载,进而触发底部导航栏重复绘制,同时页面的build方法也会因为路由层级的重复初始化而被多次调用(从你debugPrint的日志也能验证这一点)。

修复方案及代码调整

你给出的修复后的路由配置已经命中了问题核心,只需要调整路由的嵌套层级,把DictionaryRoute和OwnDictionaryRoute从RootRoute的子路由中移出,和RootRoute同级,作为HomeRoute的直接子路由即可:

修复后的路由配置(app_router.dart)

/// [AppRouter] is the router of the app
@AutoRouterConfig(replaceInRouteName: AppRouter._replaceInRouteName)
final class AppRouter extends _$AppRouter {
  static const _replaceInRouteName = 'View,Route';

  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          page: HomeRoute.page,
          initial: true,
          children: [
            AutoRoute(page: RootRoute.page),
            AutoRoute(page: DictionaryRoute.page),
            AutoRoute(page: OwnDictionaryRoute.page),
          ],
        ),
        AutoRoute(page: OTPRoute.page),
        AutoRoute(page: PhoneNumberVerificationRoute.page),
        AutoRoute(page: SignUpRoute.page),
      ];
}

关键修改点说明

  • 移除了RootRoute内部的子路由配置,将DictionaryRoute、OwnDictionaryRoute提升为HomeRoute的直接子路由
  • 这样RootView中的AutoTabsScaffold可以直接管理这两个路由,不会因为路由嵌套导致重复初始化,从根源上解决底部导航栏重复绘制和页面多次build的问题

配套的页面代码参考

为了让你更清晰地看到完整上下文,这里整理你提供的相关页面代码:

home_view.dart

/// [HomeView] is the view of home page
@RoutePage()
final class HomeView extends StatelessWidget {
  /// Constructor
  const HomeView({super.key});

  @override
  Widget build(BuildContext context) {
    debugPrint('HomeView build');
    context.read<ProductViewModel>().checkSignIn();
    return BlocSelector<ProductViewModel, ProductState, bool>(
      selector: (state) {
        return state.isSignedIn;
      },
      builder: (context, state) {
        return state ? const RootView() : const SignUpView();
      },
    );
  }
}

root_view.dart

/// [RootView] is the view of root page
@RoutePage()
final class RootView extends StatelessWidget {
  /// Constructor
  const RootView({super.key});

  @override
  Widget build(BuildContext context) {
    debugPrint('RootView build');
    return AutoTabsScaffold(
      routes: const [
        DictionaryRoute(),
        OwnDictionaryRoute(),
      ],
      bottomNavigationBuilder: (_, tabsRouter) {
        return BottomNavigationBar(
          currentIndex: tabsRouter.activeIndex,
          onTap: tabsRouter.setActiveIndex,
          items: const [
            BottomNavigationBarItem(
              icon: Icon(Icons.search_outlined),
              label: 'Dictionary',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.list_outlined),
              label: 'Own Dictionary',
            ),
          ],
        );
      },
    );
  }
}

dictionary_view.dart

/// [DictionaryView] is the view of dictionary page
@RoutePage()
final class DictionaryView extends StatefulWidget {
  /// Constructor
  const DictionaryView({super.key});

  @override
  State<DictionaryView> createState() => _DictionaryViewState();
}

class _DictionaryViewState extends State<DictionaryView>
    with DictionaryViewMixin {
  @override
  Widget build(BuildContext context) {
    debugPrint('DictionaryView build');
    return BlocProvider(
      create: (context) => dictionaryViewModel,
      child: BaseView(
        onPageBuilder: (context, value) => SliverList(
          delegate: SliverChildListDelegate(
            [
              _DictionaryBody(
                dictionaryViewModel: dictionaryViewModel,
                searchController: searchController,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

修复完成后,你可以通过debugPrint的日志验证:页面的build方法只会在必要时触发一次,底部导航栏也不会再出现重复绘制的情况了。

备注:内容来源于stack exchange,提问作者TheSylar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 09:39:35