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

Flutter中BottomNavigationBar结合BlocConsumer不重建问题求助

问题原因分析

你的问题核心出在CustomBottomNavBar的BlocConsumer使用逻辑上:

  • 在build方法内定义的int selectedIndex = 0是局部变量,每次BlocConsumer因状态变化触发builder重建时,这个变量都会被重新初始化为0。
  • 虽然listener回调里会把selectedIndex更新为state的值,但listener执行在builder重建之前,等builder执行时,又会重新将selectedIndex设为0,导致BottomNavigationBar的currentIndex始终是初始值0,无法同步选中状态。

另外,RootPage里手动维护的selectedIndex变量属于冗余状态,直接使用Bloc中的状态即可。

修复代码

修改CustomBottomNavBar.dart

移除局部变量和无用的listener,直接在builder中使用state的selectedIndex:

import 'package:cook_meet_repeat/application/root/root_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CustomBottomNavBar extends StatelessWidget {
  const CustomBottomNavBar({super.key});

  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context);

    return BlocBuilder<RootBloc, RootBottomNavigationState>(
      builder: (context, state) {
        return BottomNavigationBar(
            type: BottomNavigationBarType.fixed,
            backgroundColor: themeData.primaryColor,
            unselectedFontSize: 14,
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.set_meal_rounded),
                label: 'Events',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.groups),
                label: 'Community',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.add_circle),
                label: 'Host',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.message_rounded),
                label: 'Messages',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.person_4_rounded),
                label: 'Profile',
              ),
            ],
            currentIndex: state.selectedIndex,
            selectedItemColor: Colors.amber[800],
            selectedFontSize: 14,
            onTap: (index) {
              print("tapped on: $index");
              BlocProvider.of<RootBloc>(context).add(
                  RootBottomNavigationPressed(selectedIndex: index));
            }
        );
      });
  }
}

修改RootPage.dart

移除手动维护的selectedIndex变量,直接使用Bloc状态的索引:

import 'package:auto_route/auto_route.dart';
import 'package:cook_meet_repeat/application/auth/auth/auth_bloc.dart';

import 'package:cook_meet_repeat/application/root/root_bloc.dart';
import 'package:cook_meet_repeat/presentation/custom_bottom_nav_bar.dart';
import 'package:cook_meet_repeat/presentation/root/events/events_page.dart';
import 'package:cook_meet_repeat/presentation/root/host_events/host_events.dart';
import 'package:cook_meet_repeat/presentation/routes/router.gr.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../constants/icons.dart';

@RoutePage()
class RootPage extends StatefulWidget {
  const RootPage({super.key});

  @override
  State<RootPage> createState() => _RootPageState();
}

class _RootPageState extends State<RootPage> {
  final pages = [EventsPage(), HostEventsPage(), Placeholder(), Placeholder(), Placeholder()];

  @override
  Widget build(BuildContext context) {
    return MultiBlocListener(
      listeners: [
        BlocListener<AuthBloc, AuthState>(listener: (context, state) {
          if (state is AuthStateAuthenticated) {
            AutoRouter.of(context).push(const SignupRoute());
          }
        }),
      ],
      child: BlocBuilder<RootBloc, RootBottomNavigationState>(
        builder: (context, state) {
          return Scaffold(
              body: pages[state.selectedIndex],
              bottomNavigationBar: const CustomBottomNavBar());
        },
      ),
    );
  }
}
额外说明
  • 当只需要根据状态更新UI时,使用BlocBuilder即可,BlocConsumer仅在需要监听状态变化执行非UI操作(如跳转、弹框)时才需要。
  • 状态管理遵循单一数据源原则,尽量直接使用Bloc中的状态,避免在Widget层维护重复状态,减少状态不一致的风险。

内容的提问来源于stack exchange,提问作者Cxyda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 12:08:13