运行 Dart 中的一次多个异步请求。正确的方式
Running Multiple Async Requests at Once in Dart. Proper way
我正在尝试在 Flutter 中使用并发,所以我有三个来自服务器的获取请求,我需要同时从它们获取值。每个请求都被解析为一个模型。现在我想弄清楚如何将所有模型与三个 get-request 合并到一个列表中,运行 这是 ListView.builder 中的最终列表。此外,对于像我这样的菜鸟来说,我的任务非常艰巨,因为除了同时解析所有三个列表外,我还需要将它们过滤掉,因为如 API 中所述,所有请求都是嵌套的并且取决于 id。我该如何解决这个问题?
这是我的模型:
ScheduleVariants{
final int mrId;
final int mvId;
ScheduleVariants({this.mrId, this.mvId});
}
FlightCard{
final int mvId;
final int stId;
FlightCard({this.mrId, this.stId});
}
Stop{
final int stId;
Stop({this.stId})
}
我需要从 Stop 模型中获取最终值。如您所见,所有模型都有嵌套结构,我无法避免这一点。
现在我正在尝试像这样进行并发调用:
class Dire extends StatefulWidget {
final int mrId;
final int mvId;
final int stId;
const Dire({Key key, this.mrId, this.mvId, this.stId}) : super(key: key);
@override
_DireState createState() => _DireState();
}
class _DireState extends State<Dire> {
@override
void initState() {
fetchData();
super.initState();
stops.where((element) => element.stId == widget.stId).toList();
card.where((element) => element.mvId == widget.mvId).toList();
sheduler.where((element) => element.mrId == widget.mrId).toList();
}
List<ScheduleVariants> sheduler;
List<FlightCard> card;
List<Stop> stops;
Future fetchData() async {
String username = '';
String password = '';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
final result = await Future.wait([
http.get(
Uri.parse(
"http://mysecurelink/getMarshVariants.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getFlightCard.php?fmt=json&mv_id"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getStops.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
]);
setState(() {
sheduler = json.decode(result[0].body) as List;
card = json.decode(result[1].body) as List;
stops = json.decode(result[2].body) as List;
});
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FutureBuilder(
future: fetchData(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: stops.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(stops[index].stTitle),
);
});
} else {
return CircularProgressIndicator();
}
}));
}
}
最后的主要任务是运行三个并行请求通过ID过滤并从Stops模型中获取数据。你怎么能做对呢?
我是菜鸟,不知道如何正确地去做,如果有人帮我解决这个问题,我会很高兴。
我将做一些假设,因为没有足够的信息:
Dire
是三个 classes ScheduleVariants
、FlightCard
和 Stop
的组合,其中 ScheduleVariants.mvId == FlightCard.mvId
和 FlightCard.stId == Stop.stId
.
- 所有三个 API 都会 return 一个列表作为他们的回应。
- 所有
ScheduleVariants
都有唯一的 mvId
,所有 FlightCards
都有唯一的 mvId
和 stId
,所有 Stops
都有唯一的 stId
.
你执行多个异步请求的方式没有错。在这种情况下,Future.wait
接收一个未来列表,return 接收一个响应列表。您面临的问题只是您不知道如何合并三个 API 请求的响应。
您似乎也混淆了状态的使用和期货的使用。至少在您提供的代码片段中,您似乎不需要在初始化后更改状态,这意味着您根本不需要使用状态。
Dire
应该只是一个模型 class.
class Dire {
final ScheduleVariants scheduleVariant;
final FlightCard flightCard;
final Stop stop;
Dire(this.scheduleVariant, this.flightCard, this.stop);
}
在您想要从 API 中获取 Dires
的小部件中,您可以在 FutureBuilder
:
中使用此函数
Future<List<Dire>> fetchData() async {
String username = '';
String password = '';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
final result = await Future.wait([
http.get(
Uri.parse(
"http://mysecurelink/getMarshVariants.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getFlightCard.php?fmt=json&mv_id"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getStops.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
]);
flightCardMap = HashMap.fromIterable(json.decode(result[1].body), (fc) => fc["mvId"], (fc) => FlightCard(fc));
stopMap = HashMap.fromIterable(json.decode(result[2].body), (s) => s["stId"], (s) => Stop(s));
return json.decode(result[0].body).map((sv) => {
flightCard = flightCardMap[sv["mvId"]];
return Dire(ScheduleVariants(sv), flightCard, stopMap[flightCard["stId"]]);
}).toList();
}
免责声明:我没有检查此代码片段是否存在语法错误,因此可能存在一些错误,但总体思路是存在的。
我正在尝试在 Flutter 中使用并发,所以我有三个来自服务器的获取请求,我需要同时从它们获取值。每个请求都被解析为一个模型。现在我想弄清楚如何将所有模型与三个 get-request 合并到一个列表中,运行 这是 ListView.builder 中的最终列表。此外,对于像我这样的菜鸟来说,我的任务非常艰巨,因为除了同时解析所有三个列表外,我还需要将它们过滤掉,因为如 API 中所述,所有请求都是嵌套的并且取决于 id。我该如何解决这个问题?
这是我的模型:
ScheduleVariants{
final int mrId;
final int mvId;
ScheduleVariants({this.mrId, this.mvId});
}
FlightCard{
final int mvId;
final int stId;
FlightCard({this.mrId, this.stId});
}
Stop{
final int stId;
Stop({this.stId})
}
我需要从 Stop 模型中获取最终值。如您所见,所有模型都有嵌套结构,我无法避免这一点。
现在我正在尝试像这样进行并发调用:
class Dire extends StatefulWidget {
final int mrId;
final int mvId;
final int stId;
const Dire({Key key, this.mrId, this.mvId, this.stId}) : super(key: key);
@override
_DireState createState() => _DireState();
}
class _DireState extends State<Dire> {
@override
void initState() {
fetchData();
super.initState();
stops.where((element) => element.stId == widget.stId).toList();
card.where((element) => element.mvId == widget.mvId).toList();
sheduler.where((element) => element.mrId == widget.mrId).toList();
}
List<ScheduleVariants> sheduler;
List<FlightCard> card;
List<Stop> stops;
Future fetchData() async {
String username = '';
String password = '';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
final result = await Future.wait([
http.get(
Uri.parse(
"http://mysecurelink/getMarshVariants.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getFlightCard.php?fmt=json&mv_id"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getStops.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
]);
setState(() {
sheduler = json.decode(result[0].body) as List;
card = json.decode(result[1].body) as List;
stops = json.decode(result[2].body) as List;
});
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: FutureBuilder(
future: fetchData(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: stops.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(stops[index].stTitle),
);
});
} else {
return CircularProgressIndicator();
}
}));
} }
最后的主要任务是运行三个并行请求通过ID过滤并从Stops模型中获取数据。你怎么能做对呢?
我是菜鸟,不知道如何正确地去做,如果有人帮我解决这个问题,我会很高兴。
我将做一些假设,因为没有足够的信息:
Dire
是三个 classesScheduleVariants
、FlightCard
和Stop
的组合,其中ScheduleVariants.mvId == FlightCard.mvId
和FlightCard.stId == Stop.stId
.- 所有三个 API 都会 return 一个列表作为他们的回应。
- 所有
ScheduleVariants
都有唯一的mvId
,所有FlightCards
都有唯一的mvId
和stId
,所有Stops
都有唯一的stId
.
你执行多个异步请求的方式没有错。在这种情况下,Future.wait
接收一个未来列表,return 接收一个响应列表。您面临的问题只是您不知道如何合并三个 API 请求的响应。
您似乎也混淆了状态的使用和期货的使用。至少在您提供的代码片段中,您似乎不需要在初始化后更改状态,这意味着您根本不需要使用状态。
Dire
应该只是一个模型 class.
class Dire {
final ScheduleVariants scheduleVariant;
final FlightCard flightCard;
final Stop stop;
Dire(this.scheduleVariant, this.flightCard, this.stop);
}
在您想要从 API 中获取 Dires
的小部件中,您可以在 FutureBuilder
:
Future<List<Dire>> fetchData() async {
String username = '';
String password = '';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
final result = await Future.wait([
http.get(
Uri.parse(
"http://mysecurelink/getMarshVariants.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getFlightCard.php?fmt=json&mv_id"),
headers: <String, String>{'authorization': basicAuth}),
http.get(
Uri.parse(
"http://mysecurelink/getStops.php?fmt=json"),
headers: <String, String>{'authorization': basicAuth}),
]);
flightCardMap = HashMap.fromIterable(json.decode(result[1].body), (fc) => fc["mvId"], (fc) => FlightCard(fc));
stopMap = HashMap.fromIterable(json.decode(result[2].body), (s) => s["stId"], (s) => Stop(s));
return json.decode(result[0].body).map((sv) => {
flightCard = flightCardMap[sv["mvId"]];
return Dire(ScheduleVariants(sv), flightCard, stopMap[flightCard["stId"]]);
}).toList();
}
免责声明:我没有检查此代码片段是否存在语法错误,因此可能存在一些错误,但总体思路是存在的。