Fetch Api Data Automatically with Interval in Flutter
Futures can have 2 states: completed or uncompleted. Futures cannot "progress", but Streams can, so for your use case Streams make more sense.
You can use them like this:
Stream.periodic(Duration(seconds: 5)).asyncMap((i) => getSakaryaAir())
periodic emits empty events every 5 seconds and we use asyncMap to map that event into another stream, which get us the data.
Here is working example:
import 'package:flutter/material.dart';import 'package:http/http.dart' as http;class ExamplePage extends StatelessWidget { Future<String> getSakaryaAir() async { String url = 'https://www.random.org/integers/?num=1&min=1&max=6&col=1&base=10&format=plain&rnd=new'; final response = await http.get(url, headers: {"Accept": "application/json"}); return response.body; } @override Widget build(BuildContext context) { return StreamBuilder( stream: Stream.periodic(Duration(seconds: 5)) .asyncMap((i) => getSakaryaAir()), // i is null here (check periodic docs) builder: (context, snapshot) => Text(snapshot.data.toString()), // builder should also handle the case when data is not fetched yet ); }}
You can refactor your FutureBuilder
to use a Future
variable instead of calling the method in the FutureBuilder
. This would require you to use a StatefulWidget
and you can set up the future in your initState
and update it by calling setState
.
So you have a future variable field like:
Future< SakaryaAir> _future;
So your initState
would look like this :
@override void initState() { super.initState(); setUpTimedFetch(); }
where setUpTimedFetch
is defined as
setUpTimedFetch() { Timer.periodic(Duration(milliseconds: 5000), (timer) { setState(() { _future = getSakaryaAir(); }); }); }
Finally, your FutureBuilder
will be changed to:
FutureBuilder<SakaryaAir>( future: _future, builder: (context, snapshot) { //Rest of your code }),
Here is a DartPad demo: https://dartpad.dev/2f937d27a9fffd8f59ccf08221b82be3