Flutter报错setState() called in constructor 短信地址null求解
问题原因
你遇到的两个问题(setState报错、短信拼接地址为空)都是基础写法错误导致的:
- setState报错根因:Flutter里的
State子类(也就是你的HomepageState)是由框架在组件挂载时自动实例化、和组件树绑定生命周期的,你手动写new HomepageState()创建出来的是完全脱离组件树的无效实例,这个实例没有绑定对应Widget、mounted状态永远为false,在这个实例上触发setState自然会抛出“构造阶段调用setState、组件未挂载”的错误。 - 地址为空根因:你调用
hs.GetAddressFromLatLong之后用了then接收结果,但没有等待异步任务执行完成就直接运行了后面的launch调起短信逻辑。Dart的异步事件流不会阻塞主线程,代码运行到then时会把回调丢到事件队列,直接往下执行launch,这时候Address还是你初始化的空字符串,等异步回调拿到地址结果的时候,短信早就已经调起发送了,自然拼不到地址内容。
修复方案
按照以下步骤调整代码即可:
- 首先把
getGeoLocationPosition、GetAddressFromLatLong这两个位置获取、地址解析的公共业务方法,从HomepageState中抽离到独立的工具类中(比如location_utils.dart),不要把可复用的业务逻辑写在和组件生命周期绑定的State子类里,从根源上避免手动实例化State的错误。 - 调整异步逻辑的执行顺序,必须等地址解析结果返回、拿到有效地址字符串之后,再执行短信调起逻辑,不要用无await的then回调打乱时序。
修复后的可参考代码如下:
ElevatedButton( onPressed:() async { // 调用抽离后的工具类静态方法,不需要实例化State Position position = await LocationUtils.getGeoLocationPosition(); print("position:"); print(position); // 等待地址解析完成拿到结果 String address = await LocationUtils.getAddressFromLatLong(position); print("解析得到的地址:$address"); // 确认拿到地址后再调起短信 launch('sms:+201100840233?body=$address'); }, child:Text('Send Location') )
如果你暂时不想抽离工具类,需要复用已经挂载在组件树上的HomepageState实例,不要手动new,通过
context.findAncestorStateOfType<HomepageState>()的方式获取合法的State实例,调用方法前可以先判断if (!mounted) return避免组件销毁后触发异常。
内容的提问来源于stack exchange,提问作者Ahmed Medhat
相关产品推荐
相关产品推荐

