flutter - 在 Dart 中一次运行多个异步请求。合适的方式
问题描述
我正在尝试在 Flutter 中使用并发,所以我有来自服务器的三个 get-request,我需要同时从它们获取值。每个请求都被解析为一个模型。现在我试图弄清楚如何将所有模型组合到一个包含三个 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
是三个类的组合ScheduleVariants
,FlightCard
以及Stop
whereScheduleVariants.mvId == FlightCard.mvId
和FlightCard.stId == Stop.stId
.- 所有三个 API 都将返回一个列表作为响应。
- 都有
ScheduleVariants
独特的mvId
,FlightCards
都有独特的mvId
和stId
,而且Stops
都有独特的stId
。
执行多个异步请求的方式没有任何问题。Future.wait
在这种情况下,接收一个期货列表并返回一个响应列表。您面临的问题只是您不知道如何合并来自三个 API 请求的响应。
您似乎还将状态的使用与期货的使用混为一谈。至少在您提供的代码片段中,您似乎不需要在初始化后更改状态,这意味着您根本不需要使用状态。
Dire
应该只是一个模型类。
class Dire {
final ScheduleVariants scheduleVariant;
final FlightCard flightCard;
final Stop stop;
Dire(this.scheduleVariant, this.flightCard, this.stop);
}
在您想要Dires
从 API 获取的小部件中,您可以在以下位置使用此函数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();
}
免责声明:我没有检查此代码片段是否存在语法错误,因此可能存在一些错误,但总体思路是存在的。
推荐阅读
- amazon-web-services - 如何在 CloudFormation 中为 CodeCommit 制作 SNS 通知
- javascript - 这是一个设计糟糕的 API 吗?
- java - 如何仅使用两个变量找到两点之间的距离,然后存储所有点并获得形状?
- ios - 静默推送通知在带有 FCM 的 iOS 中有声音,如何解决?
- c# - 如何跳过 DataTable 的某些列标题文本并在数据表 C# 中选择其余部分?
- python - 访问两个子列表中的元素而不使用python中的嵌套for循环
- apache-flink - 在 Apache Flink 中找不到方案“nfs”的文件系统实现
- python - python pandas groupby和filter函数来删除候选人的名字而不需要两次预测
- java - 显示方法
- c++ - 树路径上所有节点的乘积