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

Flutter Bloc状态变更后UI未更新问题求助

问题根源

你代码的核心问题是没有监听Bloc的状态变化——你只是在build时读取了一次CounterBloc的当前状态,但Bloc状态更新后,没有任何机制通知UI重新构建。context.read<T>()只会获取当前状态,不会订阅状态变化。

修复方案

我们需要用BlocBuilder组件来包裹依赖Bloc状态的UI部分,它会自动监听Bloc的状态更新,并在状态变化时重建内部widget。

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

// Counter event.
abstract class CounterEvent {}
class Increment extends CounterEvent {}

// Counter bloc: Recive a event and increase the count.
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((Increment event, Emitter<int> emit) {
      print('Send state: ${state + 1}');
      emit(state + 1);
    });
  }
}

// Home page event and bloc here, just as a placeholder.
class HomeEvent {}
class HomeBloc extends Bloc<HomeEvent, int> {
  HomeBloc() : super(0) {
    on<HomeEvent>((HomeEvent event, Emitter<int> emit) => emit(state + 1));
  }
}

// The parent widget, create a home bloc.
class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) => BlocProvider<HomeBloc>(
      create: (BuildContext context) => HomeBloc()..add(HomeEvent()),
      child: Builder(
        builder: _getHome,
      ));

  Widget _getHome(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text('Frame')),
        body: CounterPage(),
      );
}

// Our counter page, use bloc provider to create a new bloc.
class CounterPage extends StatelessWidget {
  const CounterPage({super.key});

  @override
  Widget build(BuildContext context) => BlocProvider<CounterBloc>(
      create: (BuildContext context) => CounterBloc(),
      child: BlocBuilder<CounterBloc, int>(
        builder: (context, state) {
          // 根据当前状态返回对应UI
          return Center(
            child: AddWidget(count: state),
          );
        },
      ));
}

// As the sub widget, use the counter bloc from context.
class AddWidget extends StatelessWidget {
  const AddWidget({required this.count, super.key});

  final int count;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '$count',
            style: const TextStyle(fontSize: 24),
          ),
          const SizedBox(height: 20),
          FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () {
              print('Send increment event.');
              context.read<CounterBloc>().add(Increment());
            },
          )
        ],
      ),
    );
  }
}

关键修改点

  1. 替换Builder为BlocBuilder:在CounterPage中,用BlocBuilder<CounterBloc, int>替代原来的Builder,这样每当CounterBloc的状态更新时,builder方法会自动调用,UI随之重建。
  2. 简化CounterPage的实现:将CounterPage改为无状态组件,直接在BlocProvider的create方法中初始化CounterBloc,不需要在State中存储实例,避免内存管理问题。
  3. 直接传递Bloc状态:在BlocBuilder的builder参数中直接获取当前状态state,传递给AddWidget,确保UI显示最新值。

额外说明

  • 如果需要更精细的状态监听(比如只在特定状态变化时更新),可以给BlocBuilder添加buildWhen参数,例如:
    BlocBuilder<CounterBloc, int>(
      buildWhen: (previous, current) => current % 2 == 0,
      builder: (context, state) { ... },
    )
    
    这样只有当状态变为偶数时,才会触发UI重建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:17:08