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

Flutter Bloc问题:触发新事件后状态未更新,导航失效

问题修复方案

核心问题:多Bloc实例导致状态不共享

你代码里存在两个完全独立的AppBloc实例:

  • 在_MyAppState中手动初始化了appBloc变量,按钮点击时用它发送NavigatorButtonPressed事件
  • 但BlocProvider的create方法又新建了另一个AppBloc,BlocListener和BlocBuilder实际监听的是这个Provider内的实例

两个实例状态完全隔离,所以手动调用appBloc.add(...)触发的状态变化,Provider里的BlocListener根本感知不到。

修复步骤:

  1. 移除手动创建的Bloc实例,统一使用BlocProvider提供的实例
  2. 删除BlocBuilder内重复发送事件的代码,避免无限重绘循环
  3. 确保事件触发和状态监听使用同一个Bloc实例

修复后的完整代码

1. Bloc代码(无需修改)

import 'package:bloc/bloc.dart';
import 'package:bloctest/bloc/events.dart';
import 'package:bloctest/bloc/states.dart';

class AppBloc extends Bloc<AppEvent,AppState>{

  AppBloc(AppState initialState):super(initialState){

    on<AppStartEvent>((event, emit) {
      emit(AppInitState());
    });

    on<NavigatorButtonPressed>((event, emit) {
      emit(NavigationSucceedState());
      print('navigation succeed');
    });
  }
}

2. BlocListener页面(修复后)

import 'package:bloctest/bloc/bloc.dart';
import 'package:bloctest/bloc/states.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'bloc/events.dart';
import 'main2.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<AppBloc>(
        create: (context) => AppBloc(AppInitState())..add(AppStartEvent()),
        child: Scaffold(
          body: BlocListener<AppBloc, AppState>(
            listener: (context, state) async {
              if (state is NavigationSucceedState) {
                await Future.delayed(const Duration(seconds: 1));
                Navigator.push(context, MaterialPageRoute(builder: (context) => MyApp2()));
              }
            },
            child: BlocBuilder<AppBloc, AppState>(
              builder: (context, state) {
                return state is AppStartingState 
                    ? const Center(child: CircularProgressIndicator())
                    : Scaffold(
                        body: SafeArea(
                          child: Center(
                            child: ElevatedButton(
                              onPressed: () => context.read<AppBloc>().add(NavigatorButtonPressed()),
                              child: const Text('点击跳转到下一页'),
                            ),
                          ),
                        ),
                      );
              },
            ),
          ),
        ),
      ),
    );
  }
}

额外说明

  • BlocProvider的核心作用是在Widget树中共享Bloc实例,所有子Widget必须通过context.read()或context.watch()获取同一个实例,才能保证状态同步
  • 绝对不要在BlocBuilder的build方法内发送事件,否则每次Widget重绘都会触发事件,导致无限循环和严重性能问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:05:25