Obafemi Emmanuel

Working with APIs & Networking in Flutter

Published 3 months ago

Flutter provides powerful networking capabilities to fetch, send, and process data over the internet. Whether you're working with simple HTTP requests or complex API interactions, Flutter offers various packages like http and dio to streamline the process. In this article, we will cover:

  1. HTTP Requests using http Package
  2. Fetching & Displaying Data from API
  3. Handling JSON Parsing in Flutter
  4. Dio Package for Advanced Networking
  5. Consuming REST APIs in Flutter

1️⃣ HTTP Requests using http Package

The http package is one of the most widely used solutions for handling network requests in Flutter. To get started, add the http package to your pubspec.yaml:

dependencies:
  http: ^0.14.0  # Check for the latest version

Making a GET Request

Here’s how you can fetch data from an API:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
  
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body);
    print(data);
  } else {
    throw Exception('Failed to load data');
  }
}

Making a POST Request

Future<void> postData() async {
  final response = await http.post(
    Uri.parse('https://jsonplaceholder.typicode.com/posts'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({'title': 'Flutter API', 'body': 'Networking in Flutter', 'userId': 1}),
  );
  
  if (response.statusCode == 201) {
    print('Data posted successfully');
  } else {
    throw Exception('Failed to post data');
  }
}

2️⃣ Fetching & Displaying Data from API

Once you fetch data from an API, you need to display it in the UI. Here’s how you can use FutureBuilder to handle API calls in a Flutter widget:

class DataScreen extends StatefulWidget {
  @override
  _DataScreenState createState() => _DataScreenState();
}

class _DataScreenState extends State<DataScreen> {
  Future<Map<String, dynamic>> fetchData() async {
    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    return jsonDecode(response.body);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('API Data')),
      body: FutureBuilder(
        future: fetchData(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          }
          return Center(child: Text(snapshot.data['title']));
        },
      ),
    );
  }
}

3️⃣ Handling JSON Parsing in Flutter

APIs return JSON responses that need to be converted into Dart objects. We use model classes for structured JSON parsing.


Creating a Model Class

class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

Parsing JSON into Dart Model

Future<Post> fetchPost() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
  return Post.fromJson(jsonDecode(response.body));
}

4️⃣ Dio Package for Advanced Networking

The dio package is a robust alternative to http, offering additional features like interceptors, form data, and cancelable requests.


Installing dio

dependencies:
  dio: ^5.0.0  # Check for latest version

Making a GET Request using Dio

import 'package:dio/dio.dart';

Future<void> fetchDioData() async {
  Dio dio = Dio();
  final response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
  print(response.data);
}

Handling Error Responses

try {
  final response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
  print(response.data);
} catch (e) {
  print('Error: $e');
}

5️⃣ Consuming REST APIs in Flutter

Here’s how you can structure your project for better API consumption:


API Service Class

class ApiService {
  final Dio _dio = Dio();

  Future<Post> getPost() async {
    final response = await _dio.get('https://jsonplaceholder.typicode.com/posts/1');
    return Post.fromJson(response.data);
  }
}

Using the API in a Widget

class PostScreen extends StatefulWidget {
  @override
  _PostScreenState createState() => _PostScreenState();
}

class _PostScreenState extends State<PostScreen> {
  final ApiService apiService = ApiService();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Post Data')),
      body: FutureBuilder(
        future: apiService.getPost(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          }
          return Center(child: Text(snapshot.data!.title));
        },
      ),
    );
  }
}

Conclusion

Flutter makes it easy to work with APIs using packages like http and dio. By structuring your API calls properly, handling JSON parsing efficiently, and managing API errors, you can build powerful applications that consume RESTful services effectively.


Leave a Comment


Choose Colour