Flutter中如何通过全局变量获取Future函数内的变量值
问题原因
你的代码拿不到值核心是两个问题:
StatelessWidget是不可变组件,内部声明的成员变量value1不属于可维护的可变状态,就算赋值也不会被组件持有感知,本质上你写在StatelessWidget里的可变成员变量每次组件重建都会重置成初始值。savedata是Future异步方法,你在按钮点击事件里直接调用savedata(context)没有加await等待,调用后会立刻执行后续逻辑,这时候savedata内部的赋值代码还没跑完,你立刻读value1拿到的只能是初始的null。- 额外语法问题:你把
@override注解错放在了inputtext声明上方,正确位置应该标在build方法上,另外不要导入flutter/src/路径下的内部文件,会有版本兼容风险。
解决方案
推荐方案:改用StatefulWidget维护状态(符合Flutter官方状态管理规范)
直接把组件改成StatefulWidget,可变状态放到State类中,调用异步方法时等待执行完成再做后续操作,修正后代码如下:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); @override State<LoginScreen> createState() => _LoginScreenState(); } class _LoginScreenState extends State<LoginScreen> { final TextEditingController inputtext = TextEditingController(); String? value1; @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Center( child: SizedBox( width: 300, child: Column( children: [ TextField( controller: inputtext, decoration: const InputDecoration( border: OutlineInputBorder(), label: Text('Enter your name') ), ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: () async { // 等待异步存值、赋值逻辑全部执行完成 await savedata(context); // 此时读取value1就是更新后的值 debugPrint('当前获取到的value1值:$value1'); }, icon: const Icon(Icons.arrow_right), label: const Text('click Here') ) ], ), ), ), ), ); } Future<void> savedata(BuildContext context) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); // 等待写入完成 await prefs.setString('Name', inputtext.text.trim()); final String? savedValue = prefs.getString('Name'); debugPrint('存储的savedValue值:$savedValue'); if (savedValue == 'jibi' && context.mounted) { Navigator.of(context).pushNamed('Screen_2'); } // 赋值时通过setState触发界面更新,如果不需要更新界面也可直接赋值 setState(() { value1 = savedValue; }); } }
关键修改点:
- 替换StatelessWidget为StatefulWidget,将可变变量、控制器全部放到State类中管理,赋值后通过
setState可以同步刷新所有用到value1的界面位置 - 按钮点击回调改为异步,调用
savedata时加await,等所有异步逻辑执行完毕再读取value1,解决时序问题 - 路由跳转前增加
context.mounted判断,避免异步操作完成后组件已经销毁导致的运行时报错 - 移除了错误的src路径导入,修正了
@override注解位置
备选方案:使用顶级全局变量(不推荐,易出现值污染、难维护)
如果你一定要用全局变量,需要把value1声明在类的外部作为顶级变量,同样需要等待异步方法执行完成再读取:
// 顶级全局变量,声明在所有类外部 String? globalValue1; class LoginScreen extends StatelessWidget { LoginScreen({Key? key}) : super(key: key); final TextEditingController inputtext = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Center( child: SizedBox( width: 300, child: Column( children: [ TextField( controller: inputtext, decoration: const InputDecoration( border: OutlineInputBorder(), label: Text('Enter your name') ), ), const SizedBox(height: 16), ElevatedButton.icon( onPressed: () async { await savedata(context); debugPrint('全局变量值:$globalValue1'); }, icon: const Icon(Icons.arrow_right), label: const Text('click Here') ) ], ), ), ), ), ); } Future<void> savedata(BuildContext context) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('Name', inputtext.text.trim()); final String? savedValue = prefs.getString('Name'); if (savedValue == 'jibi') { Navigator.of(context).pushNamed('Screen_2'); } globalValue1 = savedValue; } }
核心注意点:所有返回Future的异步方法,如果你需要依赖它内部的执行结果,必须使用
await等待方法执行完成,否则代码会直接跳过异步逻辑往下执行,永远拿不到你预期的赋值结果。
内容的提问来源于stack exchange,提问作者Jibi Joseph
相关产品推荐
相关产品推荐

