Flutter报错:setState()或markNeedsBuild()在build期间调用是什么意思?
解决“setState() or markNeedsBuild() called during build”错误
错误原因
这个错误的核心是:你在Loading页面的build方法中直接调用了Navigator.pushNamed,而build方法本身是Flutter用来构建当前Widget树的过程,此时发起页面导航会触发新的Widget树构建,两个构建操作冲突,导致Flutter抛出该错误。
同时你的代码还存在两个关键问题:
setupWorldTime方法未被调用,导致WorldTime的getTime异步逻辑完全没执行- 没有在获取到时间数据后再跳转首页,无法将时间数据传递给Home页面
解决方案
- 将导航逻辑从build方法中移除,放到
initState里的异步操作完成后执行 - 在
initState中调用setupWorldTime,等时间数据获取完毕后再跳转到Home页面,并传递必要数据
修改后的Loading页面代码
import 'package:flutter/material.dart'; import 'package:world_time/services/world_time.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; class Loading extends StatefulWidget { const Loading({super.key}); @override State<Loading> createState() => _LoadingState(); } class _LoadingState extends State<Loading> { void setupWorldTime() async { WorldTime instance = WorldTime(location: "Kolkata", url: "Asia/Kolkata"); await instance.getTime(); // 异步操作完成后再导航,同时传递时间数据 if(mounted) { // 避免页面已销毁时触发导航报错 Navigator.pushReplacementNamed(context, "/home", arguments: { 'location': instance.location, 'time': instance.time, 'flag': instance.flag }); } } @override void initState() { super.initState(); setupWorldTime(); // 调用异步初始化方法 } @override Widget build(BuildContext context) { // build方法仅负责构建当前Loading页面的UI,不再处理导航 return const Scaffold( backgroundColor: Colors.blue, body: SpinKitWanderingCubes( color: Colors.green, size: 50.0, ), ); } }
补充说明
- 使用
Navigator.pushReplacementNamed替代pushNamed,可将Loading页面从导航栈中移除,用户返回时不会回到启动页,符合启动页逻辑 - 加入
mounted判断是为了防止异步操作完成后,当前页面已被销毁(比如用户快速返回),此时调用导航会触发报错 - 在Home页面可通过
ModalRoute.of(context)!.settings.arguments接收传递的时间数据
内容的提问来源于stack exchange,提问作者Sanchit Batra
相关产品推荐
相关产品推荐

