运行 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模型中获取数据。你怎么能做对呢?

我是菜鸟,不知道如何正确地去做,如果有人帮我解决这个问题,我会很高兴。

我将做一些假设,因为没有足够的信息:

  1. Dire 是三个 classes ScheduleVariantsFlightCardStop 的组合,其中 ScheduleVariants.mvId == FlightCard.mvIdFlightCard.stId == Stop.stId.
  2. 所有三个 API 都会 return 一个列表作为他们的回应。
  3. 所有 ScheduleVariants 都有唯一的 mvId,所有 FlightCards 都有唯一的 mvIdstId,所有 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();
  }

免责声明:我没有检查此代码片段是否存在语法错误,因此可能存在一些错误,但总体思路是存在的。