Reputation: 2801
I need to call two api endpoints from a single futurebuilder and combine there results into a single return list variable. I can call a single http endpoint and return the results, I'm not sure how to do two separate http calls concurrently from a single request.
Upvotes: 4
Views: 7652
Reputation: 2973
Richard Heap's answer is pretty on point and therefore the correct one. If people struggling with testing their scenarios and dont want to do REST calls, i created kind of mock futures where its easy to play with. You can define how long those two futures run and see the results by playing around with the code.
The application should be runnable on the device without changing something.
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData.dark(),
initialRoute: MyHomePage.id,
routes: {
MyHomePage.id: (context) => MyHomePage(),
},
);
}
}
class MyHomePage extends StatelessWidget {
static const String id = "HOMESCREEN";
Future<String> createFuture(String name, int seconds) {
final c = new Completer<String>();
new Timer(Duration(seconds: seconds), () {
c.complete("$name resultString");
});
return c.future;
}
Future myFutureMethodOverall() async {
Future<String> future1 = createFuture("Future1", 1); // will take 1 sec
Future<String> future2 = createFuture("Future2", 3); // will take 3 secs
return await Future.wait([future1, future2]);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
child: FutureBuilder(
future: myFutureMethodOverall(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
print(snapshot.connectionState);
if (snapshot.hasData) {
if (snapshot.data != null) {
return Container(
child:
Text("Futures complete with Data ${snapshot.data}"));
} else {
return Row(
children: <Widget>[
Container(
width: 300,
child: Text(
"Waiting for both Futures to complete...")),
new CircularProgressIndicator(),
],
);
}
} else {
return Row(
children: <Widget>[
Container(
width: 300,
child: Text(
"Waiting for both Futures to complete...")),
new CircularProgressIndicator(),
],
);
}
})),
);
}
}
At least this code helped me understand better the way futures work when having two of them which should be aligned somehow.
Upvotes: 2
Reputation: 51751
Each HTTP request will return a future. In an async
method, add both futures to a list. Then wait for both to complete with await Future.wait(theList)
.
Then process both return codes, bodies, etc, combining the results however you'd like, and return the processed, combined value. In your future builder you'll receive this result.
See Dartlang wait more than one future
For example:
Future<List<Map<String, dynamic>>> getDoubleData() async {
var value = <Map<String, dynamic>>[];
var r1 = http.get('https://www.dart.dev');
var r2 = http.get('https://www.flutter.dev');
var results = await Future.wait([r1, r2]); // list of Responses
for (var response in results) {
print(response.statusCode);
// todo - parse the response - perhaps JSON
value.add(json.decode(response.body));
}
return value;
}
Upvotes: 8