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 
httppackage in Flutter to make network requests. - Asynchronous Programming: Handling asynchronous operations using 
asyncandawait. - 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 
httpfor making network requests anddart:convertfor JSON parsing. - Stateful Widget: We create a 
StatefulWidgetto 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.postmethod to send data to the server. - Headers: We set the 
Content-Typeheader 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.builderto 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 
httppackage. - Handling asynchronous operations with 
asyncandawait. - 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
 
