Introduction
Hi friends!! In this article, we will learn about how to fetch API data using FutureBuilder Widget in Flutter. To fetch API data and display it on screen very basic and common task. We can fetch data API data without FutureBuilder but if you want to make your code more simple and reliable and auto-manage, then the FutureBuilder widget is one of the best choices to use for fetching API data.
What is FutureBuilder?
In Flutter, a FutureBuilder is a useful widget that helps us to display different content in our app based on the state of a Future. A Future is like a result or error that something will be available in the future. The cool thing about FutureBuilder, it takes care of watching the "Future" for you. It will automatically rebuild your app's screen when the "Future" is done, and it will show the appropriate content based on whether the task is still running or completed.
Basic Syntax
FutureBuilder<String>(
future: fetchData(), // This is your Future task that fetches data
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// While the task is happening, show a loading spinner
return CircularProgressIndicator();
} else if (snapshot.hasError) {
// If there's an error, display an error message
return Text('Error: ${snapshot.error}');
} else {
// When the task is done, show the fetched data
return Text('Fetched Data: ${snapshot.data}');
}
},
)
Example
We are going to fetch the below API Response data.
API URL: https://jsonplaceholder.typicode.com/posts
API Response
[{
"userId": 10,
"id": 96,
"title": "quaerat velit veniam amet cupiditate aut numquam ut sequi",
"body": "in non odio excepturi sint eum\nlabore voluptates vitae quia qui et\ninventore itaque rerum\nveniam non exercitationem delectus aut"
},
{
"userId": 10,
"id": 97,
"title": "quas fugiat ut perspiciatis vero provident",
"body": "eum non blanditiis soluta porro quibusdam voluptas\nvel voluptatem qui placeat dolores qui velit aut\nvel inventore aut cumque culpa explicabo aliquid at\nperspiciatis est et voluptatem dignissimos dolor itaque sit nam"
},
{
"userId": 10,
"id": 98,
"title": "laboriosam dolor voluptates",
"body": "doloremque ex facilis sit sint culpa\nsoluta assumenda eligendi non ut eius\nsequi ducimus vel quasi\nveritatis est dolores"
},
{
"userId": 10,
"id": 99,
"title": "temporibus sit alias delectus eligendi possimus magni",
"body": "quo deleniti praesentium dicta non quod\naut est molestias\nmolestias et officia quis nihil\nitaque dolorem quia"
},
{
"userId": 10,
"id": 100,
"title": "at nam consequatur ea labore ea harum",
"body": "cupiditate quo est a modi nesciunt soluta\nipsa voluptas error itaque dicta in\nautem qui minus magnam et distinctio eum\naccusamus ratione error aut"
}
]
Let's start with Android Studio,
Create New Flutter Project In Android Studio
Open your Android Studio and create a new project. Edit the project name, android language, iOS language, and platform, and click Create button.
Add Required Dependancy In Pubspec.yaml
Add the following dependency in pubspec.yaml file, and please click on the pub get button.
http: ^0.13.5
HTTP Package
HTTP is a network library that allows us to make HTTP requests to the web server and receive responses. HTTP package allows us to perform operations such as making GET and POST requests.
Create a Model Class
Create a new file named ResponseModel.dart and add the below code
class ResponseModel {
int? userId;
int? id;
String? title;
String? body;
ResponseModel({
this.userId,
this.id,
this.title,
this.body,});
ResponseModel.fromJson(dynamic json) {
userId = json['userId'];
id = json['id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['userId'] = userId;
map['id'] = id;
map['title'] = title;
map['body'] = body;
return map;
}
}
Open Main.dart
Go to main. dart and create a method for fetching API data
Future<List<ResponseModel>> fetchData() async {
// Replace this URL with your API endpoint
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
final data = json.decode(response.body) as List<dynamic>;
return data.map((json) => ResponseModel.fromJson(json)).toList();
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load data');
}
}
Now call the above fetchData() method from the FutureBuilder widget.
FutureBuilder<List<ResponseModel>>(
future: fetchData(),
builder: (BuildContext context, AsyncSnapshot<List<ResponseModel>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final post = snapshot.data![index];
return ListTile(
title: Text(post.title!),
subtitle: Text(post.body!),
);
},
);
}
},
)
In this example, the fetchData() method parses the JSON array and maps each JSON object to a ResponseModel object. The FutureBuilder widget displays a ListView of the ListTile widget, where each ListTile represents a ResponseModel with its title and body.
Full Code Snippet
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'ResponseModel.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body:
FutureBuilder<List<ResponseModel>>(
future: fetchData(),
builder: (BuildContext context, AsyncSnapshot<List<ResponseModel>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final post = snapshot.data![index];
return ListTile(
title: Text(post.title!),
subtitle: Text(post.body!),
);
},
);
}
},
)
);
}
Future<List<ResponseModel>> fetchData() async {
// Replace this URL with your API endpoint
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
final data = json.decode(response.body) as List<dynamic>;
return data.map((json) => ResponseModel.fromJson(json)).toList();
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load data');
}
}
}
Output
Conclusion
In this article, we have seen how to fetch API data using FutureBuilder Widget in Flutter. Thanks for reading, and hope you like it. If you have any suggestions or queries about this article, please share your thoughts. You can read my other articles by clicking here.
Happy learning, friends!