Dart语言如何将Future<List<Map>转成List<Map>?
How to transform Future<List<Map> to List<Map> in Dart language?
我对使用 Dart 语言进行编码有疑问。如何将 Future 转换为普通列表?在我的程序中,我需要来自网络的结果才能继续下一步,但我不知道该怎么做。
就我而言,我需要 return 变量 "data" 的值作为列表。
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;
}
}
但是好像没有执行网络部分。
flutter 代码部分似乎不能接受 Future。
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"])
);
}
)
);
}
}
您应该将 getList
方法重写为 return a Future<List>
. It's possible to do this with a chain of then()
invocations, but far more readable IMO to use async
/await
.
一旦你有了一个 return 是 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']}'),
);
},
);
}
)
);
}
}
你无法避免异步。
在 Dart 中,函数 return 是一个值或 Future
。当函数 return 的结果尚未准备好时,它 return 是未来,它只会在以后可用。
这意味着如果您只有一个 Future
并且您现在想要该值,那么您将陷入困境,因为该值还不存在。你现在不能returnList
,因为Future<List>
现在没有列表,以后才有。
因此,您必须等待那个未来,var data = await client.getUrl(...)...
,这意味着您的函数也必须是异步的。
因此,将 getList
函数 return 设为 Future<List>
而不是 List
,因为它只能做到这一点。
Dart 不支持的替代方法是阻塞操作,它会停止执行直到值可用,然后继续正常执行。这是单线程语言(如 Dart 和 JavaScript,Dart 必须编译成)中的一个问题,因为阻塞意味着什么都不会发生并且 UI 变得无响应。
因此,如果您的结果取决于未来的价值,那么您的函数也必须是异步的,并且 return 它自己的结果作为未来。
我对使用 Dart 语言进行编码有疑问。如何将 Future 转换为普通列表?在我的程序中,我需要来自网络的结果才能继续下一步,但我不知道该怎么做。 就我而言,我需要 return 变量 "data" 的值作为列表。
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;
}
}
但是好像没有执行网络部分。 flutter 代码部分似乎不能接受 Future。
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"])
);
}
)
);
}
}
您应该将 getList
方法重写为 return a Future<List>
. It's possible to do this with a chain of then()
invocations, but far more readable IMO to use async
/await
.
一旦你有了一个 return 是 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']}'),
);
},
);
}
)
);
}
}
你无法避免异步。
在 Dart 中,函数 return 是一个值或 Future
。当函数 return 的结果尚未准备好时,它 return 是未来,它只会在以后可用。
这意味着如果您只有一个 Future
并且您现在想要该值,那么您将陷入困境,因为该值还不存在。你现在不能returnList
,因为Future<List>
现在没有列表,以后才有。
因此,您必须等待那个未来,var data = await client.getUrl(...)...
,这意味着您的函数也必须是异步的。
因此,将 getList
函数 return 设为 Future<List>
而不是 List
,因为它只能做到这一点。
Dart 不支持的替代方法是阻塞操作,它会停止执行直到值可用,然后继续正常执行。这是单线程语言(如 Dart 和 JavaScript,Dart 必须编译成)中的一个问题,因为阻塞意味着什么都不会发生并且 UI 变得无响应。
因此,如果您的结果取决于未来的价值,那么您的函数也必须是异步的,并且 return 它自己的结果作为未来。