如何在initState中调用Cubit类函数实现页面初始化自动触发API请求
问题根本原因
你在UsersPage的build方法内部才创建了UsersCubit对应的BlocProvider,而initState的执行时机早于build方法,且initState使用的是UsersPage自身的父级上下文,这个上下文对应的组件树里还没有插入你在当前页build里定义的BlocProvider,自然找不到对应的Cubit实例。
可行解决方案
方案1:创建Cubit时直接调用方法(最便捷)
直接在BlocProvider的create方法中,创建完UsersCubit后立即链式调用getAllUsers,无需依赖页面的生命周期,代码修改如下:
body: BlocProvider( // 创建Cubit时直接触发数据请求 create: (context) => UsersCubit()..getAllUsers(), child: BlocConsumer<UsersCubit, UsersState>( // 其余原有代码保持不变 ), )
该方案适合仅当前页面使用该Cubit的场景,无需修改其他代码结构。
方案2:将BlocProvider提升到UsersPage的父级
如果你的Cubit需要在多个页面共享,或者不想在create方法里耦合调用逻辑,可以把BlocProvider挪到UsersPage的上层组件,比如main.dart中包裹你的路由入口:
// main.dart示例 void main() { runApp( BlocProvider( create: (context) => UsersCubit(), child: MaterialApp( home: UsersPage(), ), ) ); }
此时UsersPage的上下文已经能访问到上层的BlocProvider,你原来写在initState里的调用代码就可以正常运行。
方案3:拆分页面子组件获取可访问Provider的上下文
把BlocProvider的child部分拆成独立的StatefulWidget,新组件的上下文处于BlocProvider的子树中,就可以在新组件的initState里正常调用方法:
class UsersPage extends StatefulWidget { const UsersPage({Key? key}) : super(key: key); @override _UsersPageState createState() => _UsersPageState(); } class _UsersPageState extends State<UsersPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Users")), body: BlocProvider( create: (context) => UsersCubit(), // 拆分为独立子组件 child: UsersPageContent(), ), ); } } // 新增独立的子组件 class UsersPageContent extends StatefulWidget { const UsersPageContent({Key? key}) : super(key: key); @override _UsersPageContentState createState() => _UsersPageContentState(); } class _UsersPageContentState extends State<UsersPageContent> { @override void initState() { super.initState(); // 此时上下文可以访问到上层的BlocProvider,调用不会报错 context.read<UsersCubit>().getAllUsers(); } @override Widget build(BuildContext context) { return BlocConsumer<UsersCubit, UsersState>( // 原来的listener、builder逻辑全部移到这里即可 listener: (context, state) { if(state is UsersLoading){ print("getting users ..."); } else if (state is UsersSuccess){ print(state.data.users[1].identity!.name); } else if (state is UsersError){ print(state.errorMessage); } }, builder: (context, state) { return Stack( children: [ (state is UsersSuccess) ? listViewUsers(state.data.users) : progressBar(), ElevatedButton( onPressed: (){ context.read<UsersCubit>().getAllUsers(); }, child: Text("GET USERS"), ) ], ); }, ); } }
内容的提问来源于stack exchange,提问作者Alun Paranggi Wicaksono
相关产品推荐
相关产品推荐

