Future
executes once and returns just one
result. initState()
executed when creating a widget, this is also usually once. For your tasks it is better to use Streams
, my solution is not the best in terms of architecture, but as an example it works.
//We create a stream that will constantly read api data
Stream<String> remoteApi = (() async* {
const url = "http://jsonplaceholder.typicode.com/todos/1";
//Infinite loop is not good, but I have a simple example
while (true) {
try {
var response = await Dio().get(url);
if (response.statusCode == 200) {
//remote api data does not change, so i will add a timestamp
yield response.data.toString() +
DateTime.now().millisecondsSinceEpoch.toString();
}
//Pause of 1 second after each request
await Future.delayed(const Duration(seconds: 1));
} catch (e) {
print(e);
}
}
})();
//On the screen we are waiting for data and display it on the screen
// A new piece of data will refresh the screen
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: StreamBuilder<String>(
stream: remoteApi,
builder: (
BuildContext context,
AsyncSnapshot<String> snapshot,
) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.connectionState == ConnectionState.active ||
snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Text(
snapshot.data.toString(),
textAlign: TextAlign.center,
),
),
);
} else {
return const Center(child: Text('Empty data'));
}
} else {
return Center(child: Text('State: ${snapshot.connectionState}'));
}
},
),
);
}
Or simplest solution
Future<String> remoteApi() async {
try {
const url = "http://jsonplaceholder.typicode.com/todos/1";
var response = await Dio().get(url);
if (response.statusCode == 200) {
return response.data.toString() +
DateTime.now().millisecondsSinceEpoch.toString();
} else {
throw ("Error happens");
}
} catch (e) {
throw ("Error happens");
}
}
var displayValue = "Empty data";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text(displayValue)),
Center(
child: ElevatedButton.icon(
onPressed: () async {
displayValue = await remoteApi();
setState(() {});
},
label: const Text('Get API'),
icon: const Icon(Icons.download),
),
)
],
),
));
}