Flutter技术问题:如何将Future函数变量传递给StatefulWidget状态类
问题解决:异步获取API数据更新State变量
错误原因
datas是isDoctorActive函数内部的局部变量,外部无法直接访问,直接赋值field2Value = datas[0].field2Value会因变量未定义报错。- API请求是异步操作,组件初始化阶段(
field2Value声明时)还未拿到API返回的数据,同步赋值逻辑不成立。 - 当前Timer调用
isDoctorActive后未处理返回的Future,无法将异步获取的数据同步到state中。
修复方案
步骤1:声明state变量并设置初始值
将field2Value作为state变量,赋予默认初始值(比如false):
bool field2Value = false;
步骤2:修改异步函数,获取数据后更新state
在isDoctorActive函数中,拿到datas[0].field2Value后,通过setState更新state变量,触发组件重建:
Future<List<DataList>> isDoctorActive(String id) async { Response response = await get(Uri.parse(url + id)); if (response.statusCode == 200) { print("apicall : " + id); Map<String, dynamic> json = jsonDecode(response.body); Map<String, dynamic> body = json['data']; List<DataList> datas = [DataList.fromJson(body)]; print(datas[0].field2Value); // 更新state变量 setState(() { field2Value = datas[0].field2Value; }); return datas; } else { throw ('cannot fetch data'); } }
步骤3:优化Timer的异步调用
Timer的回调是同步的,调用异步函数时建议使用async/await避免未处理的Future:
@override void initState() { super.initState(); timer = Timer.periodic( Duration(seconds: 15), (Timer t) async { await isDoctorActive(widget.id); } ); // 初始化时立即调用一次,避免等待15秒才更新状态 isDoctorActive(widget.id); }
步骤4:添加Timer的销毁逻辑
在组件销毁时取消Timer,防止内存泄漏:
@override void dispose() { timer?.cancel(); super.dispose(); }
完整修改后的代码
class _HomeeScreenState extends State<HomeeScreen> { Timer? timer; bool field2Value = false; // 初始化为false final String url = 'https://exampleapi.com/api/calls/?check='; @override void initState() { super.initState(); timer = Timer.periodic( Duration(seconds: 15), (Timer t) async { await isDoctorActive(widget.id); } ); // 初始化时立即请求一次 isDoctorActive(widget.id); } Future<List<DataList>> isDoctorActive(String id) async { Response response = await get(Uri.parse(url + id)); if (response.statusCode == 200) { print("apicall : " + id); Map<String, dynamic> json = jsonDecode(response.body); Map<String, dynamic> body = json['data']; List<DataList> datas = [DataList.fromJson(body)]; print(datas[0].field2Value); // 更新state setState(() { field2Value = datas[0].field2Value; }); return datas; } else { throw ('cannot fetch data'); } } @override void dispose() { timer?.cancel(); // 销毁Timer super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: field2Value ? joinVideoRoom : null, child: Text("Join")), ), ); } Future<void> joinVideoRoom() async { Navigator.push( context, MaterialPageRoute( builder: (context) => NextScreen(), )); } }
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

