如何修复Flutter中Build期间调用setState()/markNeedsBuild()的异常
修复 setState() or markNeedsBuild() called during build 错误
问题根源
这个错误的核心是在组件构建(build)流程中直接调用了会修改Obx监听状态的方法:你的AlbumList组件在build方法里直接执行了albumController.generatePalette(image)和albumController.getAlbumsDetails(album_id),这两个方法内部更新了isLoading、albumBgGradientColor2等被Obx监听的变量。而Flutter框架不允许在组件构建过程中触发状态重建请求,因此抛出冲突错误。
同时你在build方法里重复调用Get.put()创建控制器实例,这会导致每次组件重建都生成新的控制器,不仅浪费资源,还会引发状态混乱。
修复方案
1. 修正控制器获取方式
将build里的Get.put()改为Get.find(),避免重复创建控制器实例(前提是控制器已在全局初始化,比如在main.dart或路由跳转前用Get.lazyPut()初始化):
// 全局初始化示例(可放在main.dart或路由跳转前) Get.lazyPut(() => AlbumController()); Get.lazyPut(() => ThemeController()); Get.lazyPut(() => LibraryController());
2. 延迟状态更新逻辑到构建完成后
使用WidgetsBinding.instance.addPostFrameCallback,确保组件第一次构建完成后再执行会修改状态的方法:
class AlbumList extends StatelessWidget { final String? name; final String? image; final String? album_id; const AlbumList({super.key, this.name, this.image, this.album_id}); @override Widget build(BuildContext context) { // 获取已初始化的控制器,避免重复创建 final albumController = Get.find<AlbumController>(); final ThemeController themeController = Get.find<ThemeController>(); final libraryController = Get.find<LibraryController>(); // 等待组件构建完成后再执行状态更新方法 WidgetsBinding.instance.addPostFrameCallback((_) { albumController.generatePalette(image); albumController.getAlbumsDetails(album_id); }); SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); // 以下原build代码保持不变... return Scaffold( // ...原内容 ); } }
3. 优化控制器内的异步逻辑(可选)
检查AlbumController中的getAlbumsDetails方法,确保状态更新符合异步流程,避免同步修改状态引发的异常:
Future<void> getAlbumsDetails(String? albumId) async { isLoading.value = true; try { // 执行网络请求或数据处理逻辑 // 更新songDetails等状态变量 } catch (e) { // 错误处理逻辑 } finally { isLoading.value = false; } }
内容的提问来源于stack exchange,提问作者Manoranjan
相关产品推荐
相关产品推荐

