Flutter按分类展示用户实现逻辑及构建报错解决咨询
按分类展示用户的实现逻辑及报错解决方法
一、按分类展示用户的核心逻辑
- 数据批量获取:通过
AllUsersProvider的getAllUsers方法从后端接口拉取所有用户数据,统一存储到userData列表中管理。 - 分类切换交互:页面顶部的横向分类列表支持点击切换,点击时更新当前选中的
_categoryId,触发视图更新。 - 实时数据过滤:基于当前选中的
categoryId,使用where方法对userData进行筛选,提取出属于该分类的用户子集。 - 多状态视图渲染:根据Provider的状态(加载中、空数据、有数据)分别展示加载指示器、空提示文本、用户网格列表。
二、"setState() or markNeedsBuild() called during build"报错解决方法
这个错误的根源是在组件构建过程中调用了notifyListeners,触发重绘请求与当前构建流程冲突,可通过以下两步解决:
1. 调整数据请求的执行时机
修改_UsersCategoryState的initState方法,使用WidgetsBinding.instance.addPostFrameCallback确保组件第一次构建完成后再执行数据请求:
@override void initState() { super.initState(); _categoryId = widget.categoryId; // 等待组件构建完成后再发起数据请求 WidgetsBinding.instance.addPostFrameCallback((_) { Provider.of<AllUsersProvider>(context, listen: false).getAllUsers(context); }); }
2. 优化Provider中的状态通知逻辑
减少不必要的notifyListeners调用,将状态更新后的通知合并,避免频繁触发重绘:
class AllUsersProvider extends ChangeNotifier { bool isLoading = false; List<UsersData>? userData = []; Future<void> getAllUsers(BuildContext context) async { isLoading = true; try { bool isConnected = await NetworkHelper.checkInternet(); if (!isConnected) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Kindly Connect to internet"))); isLoading = false; notifyListeners(); } else { final response = await ApiService.getUsers(); isLoading = false; if (response.statusCode == 200) { final jsonResponse = json.decode(response.body); if (jsonResponse.containsKey("success") && jsonResponse["success"]) { UsersModel usersModel = UsersModel.fromJson(jsonResponse); userData = usersModel.data; } } else { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Something went wrong"))); } notifyListeners(); } } catch (error) { print(error); isLoading = false; notifyListeners(); } } }
补充说明
原本在initState中直接调用getAllUsers时,方法内的notifyListeners会在组件未完成第一次构建时触发,导致框架收到重绘请求引发冲突。使用addPostFrameCallback可确保数据请求在组件构建完成后执行,此时调用notifyListeners不会干扰构建流程。
内容的提问来源于stack exchange,提问作者Mansoor Malik
相关产品推荐
相关产品推荐

