user16357470
user16357470

Reputation:

How to use nested (or several) Future.builder in Flutter?

I have three separate get requests to the server and I want to use them at the same time in one Future.builder, but at the same time I created three separate get-requests uding Future<List> to get data from these three requests. I also saw that in order to receive parallel requests, I have to use Future.wait inside the UI thread, but this gives me this error:

The element type 'Future<List<Result>>' can't be assigned to the list type 'Future<Result>'.

How can I solve these error if I need to get three parallel request at the same time for retriving data?

My Future:

   Future <List<Result>> fetchResult1(int mv_id) async {
      final url4 = 'http://linksecure/getRaceList.php?fmt=json&$mv_id';
      String username = '';
      String password = '';
      String basicAuth =
          'Basic ' + base64Encode(utf8.encode('$username:$password'));
      print(basicAuth);
      var response = await http.get(Uri.parse(url4), headers:<String, String>{'authorization': basicAuth});
      var jsonResponse = convert.jsonDecode(response.body) as List;
      return jsonResponse.map((e) => Result.fromJson(e)).toList();
    }
 Future <List<Result>> fetchResult2(int mv_id) async {
      final url4 = 'http://linksecure/getBooks.php?fmt=json&$mv_id';
      String username = '';
      String password = '';
      String basicAuth =
          'Basic ' + base64Encode(utf8.encode('$username:$password'));
      print(basicAuth);
      var response = await http.get(Uri.parse(url4), headers:<String, String>{'authorization': basicAuth});
      var jsonResponse = convert.jsonDecode(response.body) as List;
      return jsonResponse.map((e) => Result.fromJson(e)).toList();
    }
 Future <List<Result>> fetchResult3(int mv_id) async {
      final url4 = 'http://linksecure/getBookList.php?fmt=json&$mv_id';
      String username = '';
      String password = '';
      String basicAuth =
          'Basic ' + base64Encode(utf8.encode('$username:$password'));
      print(basicAuth);
      var response = await http.get(Uri.parse(url4), headers:<String, String>{'authorization': basicAuth});
      var jsonResponse = convert.jsonDecode(response.body) as List;
      return jsonResponse.map((e) => Result.fromJson(e)).toList();
    }

My Futurebuilder inside UI:

class Results extends StatelessWidget {
  final int mrId;

  const Results({Key key, this.mrId}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: FutureBuilder<List<Result>>(
            future:
                Future.wait([fetchResult1(0), fetchResult2(), fetchResult3()]),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.none &&
                  snapshot.hasData == null) {
                return Container();
              };
              return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {
                    Result project = snapshot.data[index];
                    return ListTile(
                      title: Text(project.rlLaststation),
                      subtitle: Text(project.rlLaststation),
                    );
                  });
            }));
  }
}

Also i think I need to put here my model because it seems like I did something wrong in here, so my models is:

List<Result> result1FromJson(String str) => List<Result>.from(json.decode(str).map((x) => Result.fromJson(x)));

String result1ToJson(List<Result> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

    class Result {
      Result({
        this.rlId,
        this.mrId,
        this.rlRacetype,
        this.rlFirststationId,
        this.rlLaststationId,
        this.rlFirststation,
        this.rlFirststationEn,
        this.rlLaststation,
        this.rlLaststationEn,
        this.stopList,
      });
    
      String rlId;
      int mrId;
      String rlRacetype;
      String rlFirststationId;
      String rlLaststationId;
      String rlFirststation;
      String rlFirststationEn;
      String rlLaststation;
      String rlLaststationEn;
      List<StopList> stopList;
    
      factory Result.fromJson(Map<String, dynamic> json) => Result(
        rlId: json["rl_id"],
        mrId: json["mr_id"],
        rlRacetype: json["rl_racetype"],
        rlFirststationId: json["rl_firststation_id"],
        rlLaststationId: json["rl_laststation_id"],
        rlFirststation: json["rl_firststation"],
        rlFirststationEn: json["rl_firststation_en"],
        rlLaststation: json["rl_laststation"],
        rlLaststationEn: json["rl_laststation_en"],
        stopList: List<StopList>.from(json["stopList"].map((x) => StopList.fromJson(x))),
      );
    
      Map<String, dynamic> toJson() => {
        "rl_id": rlId,
        "mr_id": mrId,
        "rl_racetype": rlRacetype,
        "rl_firststation_id": rlFirststationId,
        "rl_laststation_id": rlLaststationId,
        "rl_firststation": rlFirststation,
        "rl_firststation_en": rlFirststationEn,
        "rl_laststation": rlLaststation,
        "rl_laststation_en": rlLaststationEn,
        "stopList": List<dynamic>.from(stopList.map((x) => x.toJson())),
      };
    }
    
    class StopList {
      StopList({
        this.rcOrderby,
        this.stId,
        this.stTitle,
        this.stTitleEn,
        this.rcKkp,
      });
    
      int rcOrderby;
      int stId;
      String stTitle;
      String stTitleEn;
      RcKkp rcKkp;
    
      factory StopList.fromJson(Map<String, dynamic> json) => StopList(
        rcOrderby: json["rc_orderby"],
        stId: json["st_id"],
        stTitle: json["st_title"],
        stTitleEn: json["st_title_en"],
        rcKkp: rcKkpValues.map[json["rc_kkp"]],
      );

Upvotes: 3

Views: 3696

Answers (1)

Ehsan Askari
Ehsan Askari

Reputation: 891

write another function that merges all three

Future <List<Result>> fetchResults(int mv_id1, int mv_id2, int mv_id3) async {
    List<Result> results = [];
    final result1 = await fetchResult1(mv_id1);
    final result2 = await fetchResult2(mv_id2);
    final result3 = await fetchResult3(mv_id3);
    results.addAll(result1);
    results.addAll(result2);
    results.addAll(result3);
    return results;
}

and then use it as the future of your futureBuilder

FutureBuilder<List<Result>>(
    future: fetchResults(param1, param2, param3),
    ...

Upvotes: 2

Related Questions