我在使用dart语言进行编码时遇到了一个问题。如何将Future转换为正常List?在我的程序中,我需要从web继续下一步的结果,我不知道该怎么做。 在我的例子中,我需要将变量“data”的值作为List返回。
class _MyAppState extends State<MyApp> {
static List getList() {
var url = "http://watcherman.cn/web/json.php";
var data;
HttpClient client = new HttpClient();
client.getUrl(Uri.parse(url))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
response.transform(UTF8.decoder).listen((contents) {
String jsonContent = contents.toString();
data = JSON.decode(jsonContent);
});
});
return data;
}
}
但似乎没有执行网络部分。 扑动代码部分似乎无法接受未来。
class _MyAppState extends State<MyApp> {
static List content = getList();
@override
Widget build(BuildContext context) {
return new Container(
child: new ListView.builder(
scrollDirection: Axis.vertical,
padding: new EdgeInsets.all(6.0),
itemCount: content.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
alignment: FractionalOffset.center,
margin: new EdgeInsets.only(bottom: 6.0),
padding: new EdgeInsets.all(6.0),
color: Colors.blueGrey,
child: new Text(content[index]["title"])
);
}
)
);
}
}
答案 0 :(得分:13)
您应该重写getList
方法以返回Future<List>
。可以通过一系列then()
调用执行此操作,但使用async
/await
的IMO更易读。
一旦有了返回Future<List>
的方法,就可以使用FutureBuilder
构建一个依赖于异步计算结果的树。
import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:convert';
import 'dart:async';
void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}
class MyApp extends StatefulWidget {
State createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
static Future<List> getList() async {
var url = "http://watcherman.cn/web/json.php";
HttpClient client = new HttpClient();
HttpClientRequest request = await client.getUrl(Uri.parse(url));
HttpClientResponse response = await request.close();
return response.transform(UTF8.decoder).transform(JSON.decoder).toList();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Futures Demo'),
),
body: new FutureBuilder(
future: getList(),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (!snapshot.hasData)
return new Container();
List content = snapshot.data[0];
return new ListView.builder(
scrollDirection: Axis.vertical,
padding: new EdgeInsets.all(6.0),
itemCount: content.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
alignment: FractionalOffset.center,
margin: new EdgeInsets.only(bottom: 6.0),
padding: new EdgeInsets.all(6.0),
color: Colors.blueGrey,
child: new Text('${content[index]['title']}'),
);
},
);
}
)
);
}
}
答案 1 :(得分:4)
你无法摆脱异步。
在Dart中,函数返回值或Future
。当函数返回时,它返回结果尚未就绪的未来,它将仅在以后可用。
这意味着如果您拥有的只是Future
并且您现在想要该值,那么您就会陷入困境,因为该值尚未存在。您现在无法返回List
,因为Future<List>
现在没有列表,只有稍后才有。
所以,你必须等待那个未来,var data = await client.getUrl(...)...
,这意味着你的函数也必须是异步的。
因此,让getList
函数返回Future<List>
而不是List
,因为这就是它所能做的一切。
Dart不支持的替代方法是阻塞操作,在值可用之前停止执行,然后继续正常执行。这是单线程语言中的一个问题(如Dart和JavaScript,Dart必须编译),因为阻塞意味着没有任何反应,UI变得无法响应。
所以,如果你的结果取决于未来的价值,那么你的函数也必须是异步的,并且作为未来返回它自己的结果。