如何在单个Flutter页面中使用flutter_bloc实现两个Bloc Builder并解决报错
解决单个页面中两个BlocBuilder的红屏问题
嘿,我来帮你搞定这个问题!你遇到的“A build function returned null”红屏错误,本质是第二个BlocBuilder的builder回调在某些状态分支下返回了null——这在Flutter里是绝对不允许的,任何build函数都必须返回一个有效的Widget,哪怕是空占位组件也不能return null。
下面给你一个正确的实现示例,假设我们有两个独立的Bloc:CounterBloc(处理计数逻辑)和UserBloc(处理用户信息逻辑):
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; // 先定义两个简单的Bloc示例 class CounterBloc extends Bloc<int, int> { CounterBloc() : super(0) { on<int>((event, emit) => emit(state + 1)); } } class UserBloc extends Bloc<String, String> { UserBloc() : super("") { on<String>((event, emit) => emit("当前用户:$event")); } } class DualBlocPage extends StatelessWidget { const DualBlocPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("双Bloc示例")), body: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ // 第一个BlocBuilder:处理计数 Column( mainAxisAlignment: MainAxisAlignment.center, children: [ BlocBuilder<CounterBloc, int>( builder: (context, state) { // 必须返回非null的Widget,哪怕状态是初始值 return Text( "计数:$state", style: const TextStyle(fontSize: 20), ); }, ), ElevatedButton( onPressed: () => context.read<CounterBloc>().add(1), child: const Text("增加计数"), ), ], ), // 第二个BlocBuilder:处理用户信息 Column( mainAxisAlignment: MainAxisAlignment.center, children: [ BlocBuilder<UserBloc, String>( builder: (context, state) { // 关键:这里绝对不能return null!如果状态是空,返回占位Widget if (state.isEmpty) { return const Text("请输入用户名", style: TextStyle(color: Colors.grey)); } return Text( state, style: const TextStyle(fontSize: 20), ); }, ), SizedBox( width: 150, child: TextField( onSubmitted: (value) => context.read<UserBloc>().add(value), decoration: const InputDecoration(hintText: "输入用户名"), ), ), ], ), ], ), ); } } // 在页面入口处提供两个Bloc void main() { runApp( MultiBlocProvider( providers: [ BlocProvider(create: (_) => CounterBloc()), BlocProvider(create: (_) => UserBloc()), ], child: const MaterialApp(home: DualBlocPage()), ), ); }
接下来,给你几个排查和修复的关键点:
- 检查builder函数的所有分支:确保第二个BlocBuilder的builder里,不管什么状态(初始状态、加载状态、空状态)都有对应的Widget返回,绝对不能出现
return null的情况。如果不确定,就给一个默认的占位,比如SizedBox.shrink()或者Container()。 - 确认Bloc的提供是否正确:如果第二个Bloc没有被正确注入上下文(比如忘记在MultiBlocProvider里添加),也可能导致异常,但你说第一个正常,这个概率较低,不过可以顺便检查一下。
- 避免在builder里做异步操作:builder是同步执行的,如果你在里面嵌入异步逻辑导致返回null,也会触发这个错误,所有状态处理都要同步完成。
举个错误写法的反例,你一定要避开:
// 错误示例:状态为空时返回null BlocBuilder<SomeBloc, SomeState>( builder: (context, state) { if (state.hasData) { return Text(state.data); } // 这里return null会直接触发红屏! }, )
改成正确的写法:
// 正确示例:所有分支都返回Widget BlocBuilder<SomeBloc, SomeState>( builder: (context, state) { if (state.hasData) { return Text(state.data); } else if (state.isLoading) { return const CircularProgressIndicator(); } // 默认返回占位Widget return const SizedBox.shrink(); }, )
按照这个思路修改后,第二个BlocBuilder就不会再出现红屏报错了。
内容的提问来源于stack exchange,提问作者mohammed nabil
相关产品推荐
相关产品推荐

