首页 > 解决方案 > 在 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 模型中获取数据。你怎么能做对?

我是菜鸟,不知道如何正确地做到这一点,如果有人帮助我解决这个任务,我会非常高兴。

标签: flutterdartflutter-futurebuilder

解决方案


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

  1. Dire是三个类的组合ScheduleVariantsFlightCard以及StopwhereScheduleVariants.mvId == FlightCard.mvIdFlightCard.stId == Stop.stId.
  2. 所有三个 API 都将返回一个列表作为响应。
  3. 都有ScheduleVariants独特的mvIdFlightCards都有独特的mvIdstId,而且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();
  }

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


推荐阅读