Http 无法与颤振中异步函数中的全局变量通信
我在颤振中工作,在异步函数中与程序的其余部分通信时遇到问题。具体来说,我正在使用一个http请求(它必须是一个异步函数,所以这不是一个不同的选项),并尝试(在异步完成后)将一个先前实例化的全局变量设置为等于http请求响应的一部分 为了试着分析这个问题,我从基本的颤振项目中创建了一个最小的代码示例 下面的代码示例Http 无法与颤振中异步函数中的全局变量通信,http,asynchronous,flutter,async-await,Http,Asynchronous,Flutter,Async Await,我在颤振中工作,在异步函数中与程序的其余部分通信时遇到问题。具体来说,我正在使用一个http请求(它必须是一个异步函数,所以这不是一个不同的选项),并尝试(在异步完成后)将一个先前实例化的全局变量设置为等于http请求响应的一部分 为了试着分析这个问题,我从基本的颤振项目中创建了一个最小的代码示例 下面的代码示例 String username = 'xxx'; String password = 'xxx'; String basicAuth = 'Basic ' + base64Encode
String username = 'xxx';
String password = 'xxx';
String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password'));
String url = 'xxx';
String user_phone = '5555555555';
String locationId1 = 'xxx';
String locationId2 = 'xxx';
Map info;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Session ID:',
),
Text(
'$sessionID',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: createSessionID,
tooltip: 'Create Session ID',
child: Icon(Icons.add),
),
);
}
}
Future<void> createSessionID() async {
http.Response response = await http.post(
url,
headers: <String, String>{'authorization': basicAuth},
body: {'user_phone': user_phone, 'locationId1': locationId1, 'locationId2': locationId2},
);
info = jsonDecode(response.body);
sessionID = info['session_id'];
print (info['session_id']);
return info;
}
String用户名='xxx';
字符串密码='xxx';
字符串basicAuth='Basic'+base64Encode(utf8.encode('$username:$password'));
字符串url='xxx';
字符串user_phone='5555';
字符串位置ID1='xxx';
字符串位置ID2='xxx';
地图信息;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(widget.title),
),
正文:中(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
正文(
“会话ID:”,
),
正文(
“$sessionID”,
样式:Theme.of(context).textTheme.display1,
),
],
),
),
浮动操作按钮:浮动操作按钮(
onPressed:createSessionID,
工具提示:“创建会话ID”,
子:图标(Icons.add),
),
);
}
}
Future createSessionID()异步{
http.Response-Response=等待http.post(
网址,
标题:{'authorization':basicAuth},
正文:{'user\u phone':user\u phone,'locationId1':locationId1,'locationId2':locationId2},
);
info=jsonDecode(response.body);
sessionID=info['session_id'];
打印(信息['session_id']);
退货信息;
}
实际上,问题是我可以将值打印到异步函数内的调试控制台,但是如果我尝试将全局映射变量设置为任何值,它将始终为null,并且从不设置
我试着将它设置为Future并返回变量,但这并不能改变它仍然没有被正确设置的事实,因为它会因为未知的原因返回null
因此,在上面的示例中,如果我将其更改为:
Future<Map> createTrip() async {
<Same Code, but with
Map data = jsonDecode(response.body);
return data;
>
}
<void> updateInfo() async {
info = await createSessionID();
}
Future createTrip()异步{
}
updateInfo()异步{
info=等待createSessionID();
}
然后打印信息中的值,它仍然告诉我同样的事情,信息本身是空的。因此,它永远不会从异步函数内部设置。我只是不明白为什么
想法?想法
(编辑了两次以添加原始代码,并消除了混淆)我很确定您这里的所有内容都是正确的,您只是在更新了值之后没有告诉flifter更新小部件 确保使用新作业调用
setState
Future<void> createSessionID() async {
http.Response response = await http.post(
url,
headers: <String, String>{'authorization': basicAuth},
body: {'user_phone': user_phone, 'locationId1': locationId1, 'locationId2': locationId2},
);
info = jsonDecode(response.body);
setState(() => sessionID = info['session_id']); // <--------new code
print (info['session_id']);
return info;
}
Future createSessionID()异步{
http.Response-Response=等待http.post(
网址,
标题:{'authorization':basicAuth},
正文:{'user\u phone':user\u phone,'locationId1':locationId1,'locationId2':locationId2},
);
info=jsonDecode(response.body);
setState(()=>sessionID=info['session_id']);//所以这里的问题是,我没有正确理解未来的概念(老实说,我可能仍然没有,哈哈)
所以我认为,如果你等待一个响应,它会自动地将一个变量类型的未来更改为一个它应该是的类型的变量
那…不会发生
因此,您需要以不同的方式与程序的不同部分进行通信。我最终使用的解决方案(可能不是最好的,但它很有效,所以对我来说耸耸肩就足够了)就是使用全局变量来存储信息,然后使用getter将我的程序需要的局部变量设置为与服务器调用用来设置的全局变量相等
举个例子:
Map data; // Set globally, outside the function;
Future<void> createTrip() {
// Code for server call
data = jsonDecode(response.body);
return;
}
Map getData () {
return data;
}
Map data;//全局设置,函数外部;
未来的createTrip(){
//服务器调用代码
data=jsonDecode(response.body);
返回;
}
映射getData(){
返回数据;
}
因此,完全避免了试图返回未来并对其进行解码的问题。同样,这可能是非常低效的,我认为有更好的方法来实现它…但至少它是有效的,lol。我很困惑为什么Flatter不允许您使用wait
并通过函数返回值。您可以在何时发布代码试图通过函数传递变量,并使用await
,感谢更新的代码,以便您可以看到我在说什么。我使用“await”选项,但当我键入该行代码时,flatter会给出此错误代码,“await表达式只能在异步函数中使用。请尝试将函数体标记为'async'或'async*。”但正如您所看到的,它是一个异步函数。好的,我明白了为什么在这种情况下它不允许我等待,但它仍然不能帮助我。我需要updateInfo函数也是异步的。(愚蠢的我在之前没有弄清楚这个部分)。然而,所有这些都不能改变我可以将sessionID打印到调试控制台,但决不能在程序中的其他地方使用它的事实。为什么?当我还在处理这个问题时,我确实发现了一些其他的东西,显然我正在设置变量,但我正在调用I