FutureBuilder Widget – Flutter Widget Guide By Flutter Agency
Hope you guys are doing amazing with Flutter. Earlier we have been through StreamBuilder Widget. In this article, we will understand What is FutureBuilder Widget along with how to use it in a Flutter.
What are Future Operations?
Future operations are the operations which take time to perform and return the result later. To handle this problem, we use Asynchronous functions.
Asynchronous Functions
Asynchronous operations let your program continue other operations while the current operation is being performed. Dart uses Future objects to represent the results of asynchronous operations. To handle these operations, we can use Async/await, but it is not possible to integrate async and await on widgets. To solve this problem flutter introduced a widget called Future Builder.
What is FutureBuilder Widget in Flutter?
FutureBuilder Widget calls the future function to wait for the result, and as soon as it produces the result it calls the builder function where we build the widget.
The Default constructor of FutureBuilder Widget will look like below:
const FutureBuilder( {Key? key, required Future ? future, T? initialData, required AsyncWidgetBuilder builder} )
In the above constructor, all fields marked with @required must not be empty. Now let’s understand each property in detail.
Properties:
- Key key: This attribute key controls how one widget replaces another widget in the tree.
- T initialData: This attribute is the data that will be used to create the initial snapshot. Providing this value presumably obtained synchronously somehow when the Stream was created ensures that the first frame will show useful data. Otherwise, the first frame will be built with the value null, regardless of whether a value is available on the stream: since streams are asynchronous, no events from the stream can be obtained before the initial build.
- Future<T> future: This attribute will be the asynchronous computation to which this builder is currently connected, possibly null. If no future has yet completed, including in the case where the future is null, the data provided to the builder will be set to initialData.
- AsyncWidgetBuilder<T> builder: The build strategy currently used by this builder.
The builder is provided with an AsyncSnapshot object whose AsyncSnapshot.connectionState property will be one of the following three values:
- ConnectionState.none: In this state future is null. The AsyncSnapshot.data will be set to initialData, unless a future has previously completed, in which case the previous result persists.
- ConnectionState.waiting: In this state, future is not null but has not yet completed. The AsyncSnapshot.data will be set to initialData, unless a future has previously completed, in which case the previous result persists.
- ConnectionState.done: In this state, future is not null and has completed. If the future completed successfully, the AsyncSnapshot.data will be set to the value to which the future completed. If it completed with an error, AsyncSnapshot.hasError will be true, and AsyncSnapshot.error will be set to the error object.
StreamBuilder Widget and FutureBuilder Widget have the same behavior: They listen to changes on their respective object. And trigger a new build when they are notified of a new value.
When to use FutureBuilder Widget?
Let’s say you want to fetch data from the backend on the launch of the page and show the loader till data comes.
Tasks for FutureBuilder:
- Give the async task in the future of Future Builder.
- Based on connectionState, show message (loading, active(streams), done)
- Based on data(snapshot.hasError) show view
How to use FutureBuilder Widget in Flutter?
Consider the following code snippet to understand how to use it in a Flutter.
Create a Model class and it’s Constructor like a below:
class Job { final int? id; final String? position; final String? company; final String? description; Job({this.id, this.position, this.company, this.description}); factory Job.fromJson(Mapjson) { return Job( id: json['id'], position: json['position'], company: json['company'], description: json['description'], ); } }
Now create a Stateless Widget like the below:
Our _fetchData() will have a code snippet a like below:
Future<List<Job>> _fetchData() async { final jobsListAPIUrl = 'https://mocki.io/v1/342919cc-1497-43b8-ac03-608b2330f440'; final response = await http.get(jobsListAPIUrl); if (response.statusCode == 200) { List jsonResponse = json.decode(response.body); return jsonResponse.map((job) => new Job.fromJson(job)).toList(); } else { throw Exception('Failed to load jobs from API'); } }
Our _jobsListView will look like below:
ListView _jobsListView(data) { return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { return _tile(data[index].position, data[index].company, Icons.work); }); }
ListTile will look like below:
ListTile _tile(String title, String subtitle, IconData icon) => ListTile( title: Text(title, style: TextStyle( fontWeight: FontWeight.w500, fontSize: 20, )), subtitle: Text(subtitle), leading: Icon( icon, color: Colors.blue[500], ), );
Just like a StreamBuilder Widget we will get data using the below code snippet.
List<Job> data = snapshot.data;
The complete Source code will look like below:
import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( body: JobsListView(), ), ); } } class Job { final int? id; final String? position; final String? company; final String? description; Job({this.id, this.position, this.company, this.description}); factory Job.fromJson(Mapjson) { return Job( id: json['id'], position: json['position'], company: json['company'], description: json['description'], ); } } class JobsListView extends StatelessWidget { @override Widget build(BuildContext context) { return FutureBuilder >( future: _fetchJobs(), builder: (context, snapshot) { if (snapshot.hasData) { List
? data = snapshot.data; return _jobsListView(data); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } return CircularProgressIndicator(); }, ); } Future > _fetchJobs() async { final jobsListAPIUrl = 'https://mocki.io/v1/342919cc-1497-43b8-ac03-608b2330f440'; final response = await http.get(Uri.parse(jobsListAPIUrl)); if (response.statusCode == 200) { List jsonResponse = json.decode(response.body); return jsonResponse.map((job) => new Job.fromJson(job)).toList(); } else { throw Exception('Failed to load jobs from API'); } } ListView _jobsListView(data) { return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { return _tile(data[index].position, data[index].company, Icons.work); }); } ListTile _tile(String title, String subtitle, IconData icon) => ListTile( title: Text(title, style: TextStyle( fontWeight: FontWeight.w500, fontSize: 20, )), subtitle: Text(subtitle), leading: Icon( icon, color: Colors.blue[500], ), ); }
General Queries
- Pros of FutureBuilder Widget
1. No two flags and no setState
2. Reactive programming FutureBuilder Widget will take care of updating the view on data arrival
Conclusion:
In this article, we have been through What is FutureBuilder Widget and how to use it in a Flutter.
That’s it for today.
Still, need support for Flutter Mobile Application? We Would love to assist you.
Contemporary ventures
Recent blog
ready to get started?
Fill out the form below and we will be in touch soon!
"*" indicates required fields