Flutter Cubit中无法获取状态删除Posts列表问题求助
问题
我尝试删除通过Flutter Cubit的getPosts()方法获取的Posts对象列表,但在Cubit的deletePosts()方法里根本拿不到这些数据。查资料说state变量应该存着Cubit的所有数据,但打印state返回的是空数组。肯定是漏了基础知识点,求解决办法。
代码如下:
class PostsCubit extends Cubit<List<Post>> { final _dataService = DataService(); PostsCubit() : super([]); // 正常工作 - 获取所有帖子 Future<void> getPosts() async { print('Getting posts'); return emit(await _dataService.getPosts()); } // 搞不定怎么从getPosts()的Cubit状态里删数据 void deletePosts() { print(state); // 打印空数组 "[]" return emit(?????????); // return emit(state.clear()); // 没用 } }
展示帖子的Widget代码:
return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: BlocProvider<PostsCubit>( create: (BuildContext context) { return PostsCubit()..getPosts(); }, child: PostsView(), // 能正常展示getPosts()获取的所有帖子 ), );
解决方案
问题出在哪
- 要么你调用
deletePosts()的时候,getPosts()的异步请求还没完成,Cubit还是初始的空数组状态; - 就算状态有数据,
state.clear()是直接修改原数组,而Cubit要求状态必须是不可变的,直接改原状态不会触发UI更新,而且也不符合规范。
怎么改
第一步:确保调用删除方法前,数据已经加载完成
在UI里用BlocBuilder监听Cubit状态,等数据加载出来再显示删除按钮,避免在状态还是空的时候调用删除方法。
第二步:按Cubit的规则更新状态
永远不要直接修改state对象,必须通过emit传递新的状态实例:
- 如果是清空所有帖子,直接
emit([])就行; - 如果是删单个帖子,要基于原状态生成一个新的过滤后的数组。
修改后的完整代码
PostsCubit 代码
class PostsCubit extends Cubit<List<Post>> { final _dataService = DataService(); PostsCubit() : super([]); // 正常获取帖子 Future<void> getPosts() async { print('Getting posts'); final posts = await _dataService.getPosts(); emit(posts); } // 清空所有帖子 void deleteAllPosts() { // 这里如果数据已经加载,print会输出当前的帖子列表 print(state); emit([]); } // 示例:根据ID删除单个帖子 void deletePostById(int postId) { // 生成新数组,不修改原state final updatedPosts = state.where((post) => post.id != postId).toList(); emit(updatedPosts); } }
PostsView 代码(确保状态加载完成再操作)
class PostsView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('帖子列表')), body: BlocBuilder<PostsCubit, List<Post>>( builder: (context, posts) { // 数据还在加载时显示加载圈 if (posts.isEmpty) { return const Center(child: CircularProgressIndicator()); } return Column( children: [ // 清空所有帖子按钮 ElevatedButton( onPressed: () => context.read<PostsCubit>().deleteAllPosts(), child: const Text('清空所有帖子'), ), Expanded( child: ListView.builder( itemCount: posts.length, itemBuilder: (context, index) { final post = posts[index]; return ListTile( title: Text(post.title), trailing: IconButton( icon: const Icon(Icons.delete), // 删除单个帖子 onPressed: () => context.read<PostsCubit>().deletePostById(post.id), ), ); }, ), ), ], ); }, ), ); } }
关键提醒
- Cubit的状态必须是不可变的,所有状态更新都要通过
emit传递新的对象实例,不能直接修改原state; - 异步操作完成前,状态还是初始值,一定要等状态更新后再执行修改操作。
内容的提问来源于stack exchange,提问作者Kostnesm
相关产品推荐
相关产品推荐

