How to Use Dio Package for Networking in Flutter

How to Use Dio Package for Networking in Flutter

What is Dio?

Certainly! The Dio package is a powerful HTTP networking library for Dart and Flutter. It simplifies making network requests and handling responses. Here are some key features and examples of how to use Dio:

  1. Global Configuration and Interceptors:

    • Dio allows you to set global configurations and interceptors for all requests. You can customise headers, timeouts, and other settings.

    • Example:

        import 'package:dio/dio.dart';
        final dio = Dio();
  2. Performing GET and POST Requests:

    • You can easily make GET and POST requests:

        // GET request
        Response response = await dio.get('/demo?id=02&name=dio');
        // POST request
        response = await'/demo', data: {'id': 02, 'name': 'dio'});
  3. Concurrent Requests:

    • Dio supports making multiple concurrent requests:

        await Future.wait(['/info'), dio.get('/token')]);
  4. File Uploading and Downloading:

    • You can upload files to the server using FormData:

        import 'package:dio/dio.dart';
        import 'dart:io'; // Needed for accessing files
        // Assuming you have a method in your API service (or elsewhere) named `uploadFile`
        // and a variable named `post` of type `Post` (or your model class name) containing the data
        // Assuming the 'filePath' property exists in your Post model class
        final formData = FormData.fromMap({
          'name': 'dio',
          'file': await MultipartFile.fromFile(post.filePath, filename: 'upload.txt'),
        await ApiService.uploadFile('/info', formData); // Replace '/info' with your actual endpoint
        // Assuming you have a method in your service (or elsewhere) named `downloadFile`
        // and a variable named `downloadUrl` containing the download URL
        final directory = await getTemporaryDirectory();
        final savePath = '${directory.path}/downloaded_file.txt'; // Replace with desired filename
        await ApiService.downloadFile(downloadUrl, savePath);


      • We've assumed you have a Post model class or a similar class that represents the data you want to upload along with the file.

      • We've further assumed that your Post model class has a property named filePath that stores the path to the file you want to upload. Adjust this placeholder if the property name is different.

      • We've assumed you have methods in your API service (or a similar class) named uploadFile and downloadFile for handling uploads and downloads, respectively. Replace these with your actual method names.

Additional Notes:

  • Remember to replace placeholders like /info and downloadUrl with your actual server-side API endpoint URLs.

  • You'll need to modify the code to call these methods appropriately from your UI or other parts of your code.

  • If the structure of your code is significantly different, please provide the relevant code sections for further customisation.

  1. Listening to Upload Progress:

    • You can listen to the progress of file uploads:

          data: {'jj': 'aa' * 11},
          onSendProgress: (int sent, int total) {
            print('$sent $total');
  2. Custom Adapters and Transformers:

    • Dio allows you to create custom adapters and transformers for handling specific data formats.

How to Do Networking Using the Dio Package in Flutter

Certainly! Let’s break down the process of making API calls, creating model classes, and parsing data using the Dio package in Flutter. I’ll provide a step-by-step guide along with code examples.

Step 1: Set Up Your Flutter Project

Before we dive into working with APIs, make sure you have Flutter and Dart installed. If you haven’t already, follow the official Flutter installation guide. Create a new Flutter project using the following command:

flutter create api_example

Step 2: Add the Dio Package

To make HTTP requests, add the dio package to your pubspec.yaml file:

    sdk: flutter
  dio: ^5.4.3

Run flutter pub get to fetch the dependencies.

Step 3: Create Model Classes

To parse the JSON data received from the API, create a model class. For example:

class Post {
  final int userId;
  final int id;
  final String title;
  final String body;
  Post({required this.userId, required, required this.title, required this.body});
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
      body: json['body'],
  Map<String, dynamic> toJson() => {
    'userId': userId,
    'id': id,
    'title': title,
    'body': body,

Step 4: API Calling

import 'package:dio/dio.dart';
import 'package:flutter_api_example/post.dart';  // Import Post model
class ApiService {
  static const String baseUrl = ''; // Replace with your API endpoint
  static Future<Post> fetchPost(int postId) async {
    final dio = Dio();
    final response = await dio.get('$baseUrl/posts/$postId');
    if (response.statusCode == 200) {
      return Post.fromJson(;
    } else {
      throw Exception('Failed to fetch post: ${response.statusCode}');
  static Future<void> createPost(Post post) async {
    final dio = Dio();
    final response = await'$baseUrl/posts', data: post.toJson());
    if (response.statusCode == 201) {
      print('Post created successfully!');
    } else {
      throw Exception('Failed to create post: ${response.statusCode}');

Step 5: Fetch Data from an API and Display on Screen

Let’s create a simple Flutter app that fetches and displays data from a public API. Here’s an example:

import 'package:flutter/material.dart';
import 'package:flutter_api_example/api_service.dart';
import 'package:flutter_api_example/post.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'API Example',
      home: MyHomePage(),
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  _MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage> {
  Future<Post?> _post;
  String _errorMessage = '';
  void initState() {
    _fetchData(); // Fetch data on app launch
  Future<void> _fetchData() async {
    setState(() {
      _errorMessage = ''; // Clear any previous error messages
      _post = null;         // Reset the post state
    try {
      final post = await ApiService.fetchPost(1); // Assuming post ID is 1
      setState(() {
        _post = post;
    } on Exception catch (e) {
      setState(() {
        _errorMessage = e.toString();
      print('Error: $e');
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('API Example'),
      body: Center(
        child: Column(
          children: [
            if (_post != null)
            Text('Title: ${_post.title}'),
            if (_post != null)
            Text('Body: ${_post.body}'),
            if (_errorMessage.isNotEmpty)
                'Error: $_errorMessage',
                style: const TextStyle(color:,
              onPressed: _fetchData,
              child: const Text('Fetch Post'),
                      onPressed: () async {
                        // Example of posting data (replace with your data)
                        final post = Post(userId: 1, id: 2, title: 'New Post', body: 'Here is a new post');
                        await ApiService.createPost(post);

In this example:

  • We create a simple app with a button that triggers the fetchData function.

  • The fetchData function makes a GET request to the JSONPlaceholder API.

  • If the response status code is 200, we extract the title from the response and update the UI.

  • If there’s an error, we handle it gracefully.

Difference Between http and dio packages in Flutter

Certainly! Let’s compare the http package and the Dio package in Flutter for making API calls. Both packages serve the purpose of handling HTTP requests, but they have different features and use cases:

  1. http Package:

    • Advantages:

      • Simplicity: The http package is straightforward and easy to use. It provides basic functionality for making HTTP requests.

      • Lightweight: It’s a lightweight library, making it suitable for small projects and simple use cases.

    • Disadvantages:

      • Basic Functionality: The http package only covers the essentials for making network requests. Additional features must be implemented independently.

      • Error Handling: You need to write custom error-handling functions.

    • Use Case:

      • Ideal for small projects where development speed is crucial.
  2. Dio Package:

    • Advantages:

      • Feature-Rich: Dio is a powerful HTTP client for Dart. It offers a wide range of features beyond basic networking.

      • Interceptors: You can use interceptors for tasks like logging, caching, and modifying requests and responses.

      • Global Configuration: Customise global settings for all requests.

      • FormData and File Downloading: Supports file uploading and downloading.

      • Timeouts: Set timeouts for requests.

      • Fast and Efficient: Utilises asynchronous and parallel requests.

    • Disadvantages:

      • Complexity: Due to its extensive functionality, there’s a higher chance of encountering bugs.
    • Use Case:

      • Suitable for larger projects with long-term support.

      • When development speed is less critical, and you prioritise additional features and reliability.

  • http is simple and lightweight, while Dio provides more advanced features.

  • Choose http for small projects and quick development.

  • Opt for Dio when you need additional functionality and long-term support.

Remember that the choice depends on your project’s size, complexity, and specific requirements. Happy coding! 🚀

In conclusion, the Dio package is a robust and feature-rich HTTP client for Dart and Flutter, offering advanced capabilities like global configuration, interceptors, concurrent requests, and file handling. While the http package is suitable for smaller projects due to its simplicity and lightweight nature, Dio excels in larger, more complex applications that require extensive networking features and long-term support. By understanding the strengths and use cases of each package, developers can make informed decisions to best meet their project's needs. Happy coding! 🚀

Did you find this article valuable?

Support JoFlee by becoming a sponsor. Any amount is appreciated!