Skip to main content

Command Palette

Search for a command to run...

How to Fetch Data from the Internet in Flutter with APIs

Updated
5 min read
How to Fetch Data from the Internet in Flutter with APIs

API (Application Programming Interface)

An API (Application Programming Interface) is like a bridge that lets two software programs talk to each other. It defines how one program can request information or services from another. For example, when you use a weather app, the app asks a weather service API for the current temperature, and the API sends back the data, like "15°C and sunny."

APIs make it easy for systems to work together. For instance, an online store might use a payment gateway API to process payments. When you enter your card details, the API sends the information securely to the bank, processes the payment, and returns a response like "Payment successful." APIs are everywhere, simplifying how apps and services communicate behind the scenes.

"An API is like a waiter at a restaurant—it takes your request to the kitchen (server) and brings back exactly what you ordered, without you needing to know how it was prepared."

Store Analogy for API Requests

  1. You (Your App): Want to buy something (like a new product, which in our case is news).

  2. The Store (The API): Sells the product you need (the news articles).

  3. Your Request (HTTP Request): You go to the store and ask, "Do you have any new products?" (You’re asking for the latest news).

  4. Store's Response (HTTP Response): The store gives you the latest products (news articles) if they have them, or they say "Sorry, we don’t have it right now."

To use the http package in your Flutter project, you can simply run the command flutter pub add http in your terminal. This automatically adds the package to your project and installs it. Once the installation is complete, you can import the package into your Dart files using import 'package:http/http.dart' as http;. This allows you to easily make HTTP requests in your app.

Step 1: API Integration (Backend Logic)

This file is responsible for making the API request to the "store" (NewsAPI) and retrieving the products (news).

// File: store_service.dart
import 'package:http/http.dart' as http; // To communicate with the store (HTTP client)
import 'dart:convert'; // To decode the JSON response from the store (unwrap the box)

class StoreService {
  // Function to fetch products (news) from the store (API)
  Future<List<dynamic>> fetchProducts() async {
    final url = Uri.parse(
        'https://jsonplaceholder.typicode.com/posts'); // Store's address (API URL)

    final response = await http.get(url); // Asking the store for the latest products (request)

    if (response.statusCode == 200) {
      // If the store says, "Yes, we have the products!"
      return json.decode(response.body); // Unwrap the box (JSON) and extract the products (news articles)
    } else {
      // If the store replies with an error (no products)
      throw Exception('Failed to load products'); // Show error if the store has no products
    }
  }
}

Explanation of the Code

store_service.dart (Backend Logic)

  1. Imports:

    • We import http to make HTTP requests (ask the store for products) and dart:convert to decode the JSON data (unwrap the box containing news articles).
  2. StoreService Class:

    • This is where we define the logic for asking the store for products. The fetchProducts function sends an HTTP request to the API URL, waits for a response, and if successful, decodes the response (JSON) to extract the product data.
  3. Error Handling:

    • If the store has no products, we handle it with an exception (throw Exception('Failed to load products');).

What is 200 (OK) Response Code: Meaning, Issues with 200 Status Codes

Step 2: UI Page (Store Display)

// File: store_page.dart
import 'package:flutter/material.dart'; // For UI components (store shelves)
import 'store_service.dart'; // Asking the store for products (news)

class StorePage extends StatefulWidget {
  @override
  _StorePageState createState() => _StorePageState();
}

class _StorePageState extends State<StorePage> {
  late Future<List<dynamic>> products; // Where we keep the products (news) from the store

  @override
  void initState() {
    super.initState();
    products = StoreService().fetchProducts(); // Asking the store for the latest products (news)
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Simple Store App'), // Store's name (your app title)
      ),
      body: FutureBuilder<List<dynamic>>(
        future: products, // Waiting for the store to give us the products (news)
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator()); // While waiting, show a loading symbol
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}')); // If the store has an issue (error response)
          } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
            return Center(child: Text('No products available')); // If the store has no products (empty result)
          }

          final items = snapshot.data!; // The products (items) from the store
          return ListView.builder(
            itemCount: items.length, // How many products (news items) to display
            itemBuilder: (context, index) {
              final item = items[index]; // Each individual product (news article)
              return ListTile(
                title: Text(item['title']), // Product name (news title)
                subtitle: Text(item['body']), // Product description (news body)
              );
            },
          );
        },
      ),
    );
  }
}

store_page.dart (UI Logic)

  1. FutureBuilder:

    • We use a FutureBuilder to handle the asynchronous nature of the API request. The app will show a loading indicator while waiting for the store to respond and will display the news when available.
  2. Displaying Data/News:

    • Once the data is received, the ListView.builder dynamically creates a list of products (articles) to display, each with a title and description.
  3. Error Handling:

    • If there’s an error or no data, appropriate error messages are displayed on the UI.

3. Main File: main.dart

This file initializes the app and opens the "store" to show the products (news).

// File: main.dart
import 'package:flutter/material.dart';
import 'store_page.dart'; // The page where we see the store products (news)

void main() => runApp(StoreApp());

class StoreApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StorePage(), // Going to the store to see the products (news)
    );
  }
}

Conclusion

This article demonstrates how to fetch and display data in Flutter using the http package. By breaking the process into simple steps, we learned how to send API requests, decode JSON responses, handle errors, and display data dynamically using widgets like FutureBuilder and ListView. This example serves as a foundational guide for building apps that connect to APIs, enabling you to create dynamic, data-driven Flutter applications with real-time internet data integration.