Flutter BlocProvider异常:上下文无StateStreamableSource
解决Flutter BlocProvider上下文无StateStreamableSource的异常
代码结构
AppCubit类
import 'package:auth_todo/models/shared/cubit/states.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:sqflite/sqflite.dart'; class AppCubit extends Cubit<AppStates> { AppCubit() : super(AppInitialStates()); static get(context) => BlocProvider.of(context); int selectedIndex = 0; List<Widget> screen = [ const NewTasksScreen(), const ArchivedTasksScreen(), const DoneTasksScreen(), ]; List<String> titles = [ 'New Tasks', 'Done Tasks', 'Archived Tasks', ]; void changIndex(int index) { selectedIndex = index; emit(AppChangeBnvStates()); } }
AppStates状态类
abstract class AppStates {} class AppInitialStates extends AppStates {} class AppChangeBnvStates extends AppStates {} class AppCreateDataBaseState extends AppStates {} class AppInsertToDataBaseState extends AppStates {} class AppGetFromDataBaseState extends AppStates {} class AppChangBottomSheetState extends AppStates {}
使用BlocProvider的HomeLayout页面
// ignore_for_file: must_be_immutable import 'package:auth_todo/models/shared/cubit/states.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_nav_bar/google_nav_bar.dart'; import 'package:intl/intl.dart'; import '../models/shared/cubit/cubit.dart'; import '../widgets/components/dufalt_form_filed.dart'; import 'package:conditional_builder_null_safety/conditional_builder_null_safety.dart'; class HomeLayout extends StatelessWidget { TextEditingController taskTitelController = TextEditingController(); TextEditingController taskTimeController = TextEditingController(); TextEditingController taskDateController = TextEditingController(); var scaffoldKey = GlobalKey<ScaffoldState>(); var formKey = GlobalKey<FormState>(); HomeLayout({super.key}); @override Widget build(BuildContext context) { AppCubit cubit = AppCubit.get(context); return BlocProvider( create: (_) => AppCubit()..creatDatabase(), child: BlocConsumer<AppCubit, AppStates>( listener: (context, state) { if (state is AppInsertToDataBaseState) { Navigator.pop(context); } }, builder: (context, state) => Scaffold( key: scaffoldKey, appBar: AppBar( title: Text(cubit.titles[cubit.selectedIndex]), centerTitle: true, ), body: ConditionalBuilder( condition: true, builder: (context) => cubit.screen[cubit.selectedIndex], fallback: (context) => const Center(child: CircularProgressIndicator())), ), )); } }
异常信息
═══════════════════════════════════
构建HomeLayout(dirty)时抛出以下断言:
BlocProvider.of()调用传入的上下文不包含StateStreamableSource<Object?>。
从传入BlocProvider.of<StateStreamableSource<Object?>>()的上下文开始,未找到任何祖先组件。
这种情况可能是因为你使用的上下文来自BlocProvider上方的Widget。
使用的上下文为:HomeLayout(dirty)
引发错误的相关Widget是HomeLayout(main.dart:31)
解决方法
核心问题
你在HomeLayout的build方法开头就调用AppCubit.get(context),但此时BlocProvider还未创建,当前上下文属于HomeLayout本身,没有任何祖先BlocProvider提供AppCubit实例,因此触发断言错误。
具体修复步骤
- 删除
build方法开头的AppCubit cubit = AppCubit.get(context);,这行代码在BlocProvider实例化前执行,上下文无法找到对应Cubit。 - 在
BlocConsumer的builder方法内部获取Cubit实例,因为BlocConsumer是BlocProvider的子组件,其上下文可以访问到已创建的Cubit。 - 若需要在页面组件中使用Cubit属性,均通过
BlocConsumer内部的上下文获取。
修复后的HomeLayout代码
// ignore_for_file: must_be_immutable import 'package:auth_todo/models/shared/cubit/states.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_nav_bar/google_nav_bar.dart'; import 'package:intl/intl.dart'; import '../models/shared/cubit/cubit.dart'; import '../widgets/components/dufalt_form_filed.dart'; import 'package:conditional_builder_null_safety/conditional_builder_null_safety.dart'; class HomeLayout extends StatelessWidget { TextEditingController taskTitelController = TextEditingController(); TextEditingController taskTimeController = TextEditingController(); TextEditingController taskDateController = TextEditingController(); var scaffoldKey = GlobalKey<ScaffoldState>(); var formKey = GlobalKey<FormState>(); HomeLayout({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (_) => AppCubit()..creatDatabase(), child: BlocConsumer<AppCubit, AppStates>( listener: (context, state) { if (state is AppInsertToDataBaseState) { Navigator.pop(context); } }, builder: (context, state) { // 在BlocConsumer内部获取Cubit实例 AppCubit cubit = AppCubit.get(context); return Scaffold( key: scaffoldKey, appBar: AppBar( title: Text(cubit.titles[cubit.selectedIndex]), centerTitle: true, ), body: ConditionalBuilder( condition: true, builder: (context) => cubit.screen[cubit.selectedIndex], fallback: (context) => const Center(child: CircularProgressIndicator())), ); }, )); } }
额外优化建议
- 给
AppCubit.get方法添加泛型约束,避免类型警告:static AppCubit get(context) => BlocProvider.of<AppCubit>(context); - 确保
creatDatabase方法已正确实现,否则会出现未定义方法的编译错误。
内容的提问来源于stack exchange,提问作者Taha Mohamed
相关产品推荐
相关产品推荐

