In this section, we will explore how to use REST APIs in Flutter to fetch and manipulate data from a remote server. REST (Representational State Transfer) is a popular architectural style for designing networked applications, and it is widely used for web services.
Key Concepts
- HTTP Requests: Understanding the different types of HTTP requests (GET, POST, PUT, DELETE).
- HTTP Package: Using the
http
package in Flutter to make network requests. - Asynchronous Programming: Handling asynchronous operations using
async
andawait
. - Error Handling: Managing network errors and exceptions.
- JSON Parsing: Converting JSON data to Dart objects and vice versa.
HTTP Requests
HTTP requests are the foundation of REST APIs. Here are the most common types:
- GET: Retrieve data from the server.
- POST: Send data to the server to create a new resource.
- PUT: Update an existing resource on the server.
- DELETE: Remove a resource from the server.
Using the http
Package
To make HTTP requests in Flutter, we use the http
package. First, add the http
package to your pubspec.yaml
file:
Then, run flutter pub get
to install the package.
Making a GET Request
Let's start with a simple GET request to fetch data from a REST API.
Example: Fetching Data from a REST API
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( home: Scaffold( appBar: AppBar(title: Text('REST API Example')), body: Center(child: DataFetcher()), ), ); } } class DataFetcher extends StatefulWidget { @override _DataFetcherState createState() => _DataFetcherState(); } class _DataFetcherState extends State<DataFetcher> { String data = 'Fetching data...'; @override void initState() { super.initState(); fetchData(); } Future<void> fetchData() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1')); if (response.statusCode == 200) { setState(() { data = json.decode(response.body)['title']; }); } else { setState(() { data = 'Failed to load data'; }); } } @override Widget build(BuildContext context) { return Text(data); } }
Explanation
- Importing Packages: We import the necessary packages, including
http
for making network requests anddart:convert
for JSON parsing. - Stateful Widget: We create a
StatefulWidget
to manage the state of the fetched data. - fetchData Method: This method makes a GET request to a sample API and updates the state with the fetched data.
- Error Handling: We check the status code of the response to handle errors appropriately.
Making a POST Request
Next, let's see how to send data to a server using a POST request.
Example: Sending Data to a REST API
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( home: Scaffold( appBar: AppBar(title: Text('REST API Example')), body: Center(child: DataSender()), ), ); } } class DataSender extends StatefulWidget { @override _DataSenderState createState() => _DataSenderState(); } class _DataSenderState extends State<DataSender> { String responseMessage = 'Sending data...'; Future<void> sendData() async { final response = await http.post( Uri.parse('https://jsonplaceholder.typicode.com/posts'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'title': 'foo', 'body': 'bar', 'userId': '1', }), ); if (response.statusCode == 201) { setState(() { responseMessage = 'Data sent successfully'; }); } else { setState(() { responseMessage = 'Failed to send data'; }); } } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text(responseMessage), ElevatedButton( onPressed: sendData, child: Text('Send Data'), ), ], ); } }
Explanation
- POST Request: We use the
http.post
method to send data to the server. - Headers: We set the
Content-Type
header toapplication/json
. - Body: We encode the data as JSON using
jsonEncode
. - Response Handling: We check the status code to determine if the data was sent successfully.
Practical Exercise
Task
Create a Flutter app that fetches a list of users from a REST API and displays their names in a ListView
.
Solution
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( home: Scaffold( appBar: AppBar(title: Text('User List')), body: Center(child: UserList()), ), ); } } class UserList extends StatefulWidget { @override _UserListState createState() => _UserListState(); } class _UserListState extends State<UserList> { List<String> users = []; @override void initState() { super.initState(); fetchUsers(); } Future<void> fetchUsers() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users')); if (response.statusCode == 200) { final List<dynamic> data = json.decode(response.body); setState(() { users = data.map((user) => user['name'] as String).toList(); }); } else { setState(() { users = ['Failed to load users']; }); } } @override Widget build(BuildContext context) { return ListView.builder( itemCount: users.length, itemBuilder: (context, index) { return ListTile( title: Text(users[index]), ); }, ); } }
Explanation
- Fetching Users: We make a GET request to fetch a list of users.
- Parsing JSON: We parse the JSON response and extract the user names.
- Displaying Data: We use a
ListView.builder
to display the user names in a list.
Summary
In this section, we learned how to use REST APIs in Flutter to fetch and send data. We covered:
- Making GET and POST requests using the
http
package. - Handling asynchronous operations with
async
andawait
. - Parsing JSON data.
- Managing network errors.
In the next section, we will explore how to handle network errors more robustly and how to integrate more complex REST API interactions in your Flutter applications.
Flutter Development Course
Module 1: Introduction to Flutter
- What is Flutter?
- Setting Up the Development Environment
- Understanding Flutter Architecture
- Creating Your First Flutter App
Module 2: Dart Programming Basics
- Introduction to Dart
- Variables and Data Types
- Control Flow Statements
- Functions and Methods
- Object-Oriented Programming in Dart
Module 3: Flutter Widgets
- Introduction to Widgets
- Stateless vs Stateful Widgets
- Basic Widgets
- Layout Widgets
- Input and Form Widgets
Module 4: State Management
Module 5: Navigation and Routing
Module 6: Networking and APIs
- Fetching Data from the Internet
- Parsing JSON Data
- Handling Network Errors
- Using REST APIs
- GraphQL Integration
Module 7: Persistence and Storage
- Introduction to Persistence
- Shared Preferences
- File Storage
- SQLite Database
- Using Hive for Local Storage
Module 8: Advanced Flutter Concepts
- Animations in Flutter
- Custom Paint and Canvas
- Platform Channels
- Isolates and Concurrency
- Performance Optimization
Module 9: Testing and Debugging
Module 10: Deployment and Maintenance
- Preparing for Release
- Building for iOS
- Building for Android
- Continuous Integration/Continuous Deployment (CI/CD)
- Maintaining and Updating Your App