Flutter has become a popular choice for cross-platform mobile app development, thanks to its ease of use, rich set of widgets, and excellent performance. One common requirement in mobile apps is fetching data from REST APIs. This blog post will guide you through the process of working with REST APIs in Flutter, including how to make HTTP requests, handle responses, parse JSON data, and display it in your app.
What are REST APIs?
REST (Representational State Transfer) APIs are a widely used architectural style for designing networked applications. They allow different software systems to communicate over the internet. A REST API typically uses HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources identified by URLs.
Why Work with REST APIs in Flutter?
- Dynamic Data: Fetch real-time data from servers to keep your app updated.
- Cross-Platform Compatibility: Flutter apps can connect to any REST API, regardless of the backend technology.
- Feature Integration: Access external services, such as authentication, payment gateways, and social media platforms.
Setting Up Your Flutter Project
Before diving into the code, make sure you have a Flutter project set up. If not, create a new Flutter project using the following command:
flutter create flutter_rest_api_example
Step 1: Add the http Package
To make HTTP requests in Flutter, you’ll need the http package. Add it to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
http: ^0.13.5
Run flutter pub get to install the package.
Step 2: Making a GET Request
Let’s start by making a simple GET request to fetch data from a REST API. We’ll use the JSONPlaceholder API, which provides fake online REST APIs for testing and prototyping.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter REST API Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
final String apiUrl = 'https://jsonplaceholder.typicode.com/todos/1';
Future
In this code:
- We import the necessary packages:
flutter/material.dart,http/http.dart, anddart:convert. - The
fetchDatafunction sends a GET request to the API endpoint and parses the JSON response. - We use a
FutureBuilderto handle the asynchronous nature of the HTTP request and display the data when it’s available.
Step 3: Making a POST Request
To send data to a REST API, you can use a POST request. Here’s how to make a POST request in Flutter:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
final String apiUrl = 'https://jsonplaceholder.typicode.com/posts';
Future createPost(String title, String body, int userId) async {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode({
'title': title,
'body': body,
'userId': userId,
}),
);
return response;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('REST API Example - POST'),
),
body: Center(
child: ElevatedButton(
child: Text('Create Post'),
onPressed: () async {
final response = await createPost('My Title', 'My Body', 1);
if (response.statusCode == 201) {
// If the server did return a 201 CREATED response,
// then show a success message.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Post created successfully!')),
);
} else {
// If the server did not return a 201 CREATED response,
// then show an error message.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to create post.')),
);
}
},
),
),
);
}
}
In this example:
- The
createPostfunction sends a POST request to the API endpoint with the provided data in JSON format. - We set the
Content-Typeheader toapplication/jsonto indicate that we’re sending JSON data. - The response status code is checked to determine if the POST request was successful.
Step 4: Handling Errors
When working with REST APIs, it’s essential to handle potential errors gracefully. Here’s how you can handle errors in your Flutter app:
Future> fetchData() async {
try {
final response = await http.get(Uri.parse(apiUrl));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load data: Status code ${response.statusCode}');
}
} catch (e) {
print('Error: $e');
throw Exception('Failed to load data');
}
}
Here, we use a try-catch block to catch any exceptions that may occur during the HTTP request. We also check the status code to ensure the request was successful. If an error occurs, we print the error message to the console and throw an exception, which can be handled by the FutureBuilder.
Step 5: Parsing Complex JSON
Sometimes, the JSON response from an API can be complex, with nested objects and arrays. Here’s how you can parse complex JSON in Flutter:
import 'dart:convert';
class User {
final int userId;
final int id;
final String title;
final bool completed;
User({
required this.userId,
required this.id,
required this.title,
required this.completed,
});
factory User.fromJson(Map json) {
return User(
userId: json['userId'],
id: json['id'],
title: json['title'],
completed: json['completed'],
);
}
}
Future fetchUser() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/todos/1'));
if (response.statusCode == 200) {
return User.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load user');
}
}
In this example:
- We create a
Userclass to represent the JSON data. - The
User.fromJsonfactory method is used to parse the JSON and create aUserobject.
Conclusion
Working with REST APIs in Flutter involves making HTTP requests, handling responses, parsing JSON data, and displaying it in your app. By using the http package and following the steps outlined in this blog post, you can easily integrate REST APIs into your Flutter projects. Remember to handle errors gracefully and parse JSON data correctly to ensure your app works smoothly and efficiently. This approach allows you to build dynamic and data-driven applications that provide a rich user experience.