Fetch Api Data Automatically with Interval in Flutter
Solution 1
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
Solution 2
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
);
}
}
Şansal Birbaş
Updated on December 04, 2022Comments
-
Şansal Birbaş over 1 year
On my flutter application I am trying to show updating data. I am successful in getting data from weather api manually. But I need to constantly grab data every 5 seconds. So it should be updated automatically. Here is my code in Flutter :
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sakarya Hava', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text('Sakarya Hava'), ), body: Center( child: FutureBuilder<SakaryaAir>( future: getSakaryaAir(), //sets the getSakaryaAir method as the expected Future builder: (context, snapshot) { if (snapshot.hasData) { //checks if the response returns valid data return Center( child: Column( children: <Widget>[ Text("${snapshot.data.temp}"), //displays the temperature SizedBox( height: 10.0, ), Text(" - ${snapshot.data.humidity}"), //displays the humidity ], ), ); } else if (snapshot.hasError) { //checks if the response throws an error return Text("${snapshot.error}"); } return CircularProgressIndicator(); }, ), ), ), ); } Future<SakaryaAir> getSakaryaAir() async { String url = 'http://api.openweathermap.org/data/2.5/weather?id=740352&APPID=6ccf09034c9f8b587c47133a646f0e8a'; final response = await http.get(url, headers: {"Accept": "application/json"}); if (response.statusCode == 200) { return SakaryaAir.fromJson(json.decode(response.body)); } else { throw Exception('Failed to load post'); } } }
I found such a snippet to benefit from :
// runs every 5 second Timer.periodic(new Duration(seconds: 5), (timer) { debugPrint(timer.tick); });
Probably I need to wrap and call FutureBuilder with this snippet but I was not able to understand how to do it.
-
pianoman102 almost 3 yearshey @pr0gramist, i know this is kind of old, but I'm finding your answer useful here, with one additional question. Do you know how you would fit this into using bloc for your state management? I have a few examples that someone with your experience might be able to advise on.
-
pr0gramist almost 3 years@pianoman102 I think Timer example of the bloc is somewhat comparable: bloclibrary.dev/#/fluttertimertutorial Once you got ticker setup you can send events and fetch new data.
-
pianoman102 almost 3 yearsYeah i saw that actually, but thought it was a little overkill...I was thinking you could setup your bloc to fetch events via a repository, and then in the ui somewhere, setup a timer to send a fetchData event to the bloc on an interval. But I don't know if that's the best way or not.