How to Use the Dio Package in Flutter for Networking

When it comes to building modern mobile applications, networking is a fundamental requirement. Flutter provides the http package for making network requests, but for more advanced use cases, the dio package is a powerful and popular alternative. In this guide, you’ll learn how to use dio to handle networking in your Flutter apps with ease.


1. What is Dio?

Dio is a powerful HTTP client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout, and more. It provides a more advanced and feature-rich API compared to the standard http package, making it ideal for complex applications.


2. Add the Dio Package

First, you need to add the dio package to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.6 # Use the latest version

Then, run flutter pub get in your terminal to install the package.


3. Making HTTP Requests

Creating a Dio Instance

It’s a good practice to create a single instance of Dio and reuse it throughout your app. You can configure it with a base URL and other options.

import 'package:dio/dio.dart';

final dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: 5000,
  receiveTimeout: 3000,
));

GET Request

To make a GET request, use the get() method:

Future<void> fetchData() async {
  try {
    final response = await dio.get('/users');
    print(response.data);
  } catch (e) {
    print('Error: $e');
  }
}

POST Request

To make a POST request, use the post() method and pass the data in the data parameter:

Future<void> createUser() async {
  try {
    final response = await dio.post('/users', data: {
      'name': 'John Doe',
      'email': 'john.doe@example.com',
    });
    print('User created: ${response.data}');
  } catch (e) {
    print('Error: $e');
  }
}

PUT Request

To update data, use the put() method:

Future<void> updateUser() async {
  try {
    final response = await dio.put('/users/1', data: {
      'name': 'Jane Doe',
    });
    print('User updated: ${response.data}');
  } catch (e) {
    print('Error: $e');
  }
}

DELETE Request

To delete data, use the delete() method:

Future<void> deleteUser() async {
  try {
    final response = await dio.delete('/users/1');
    print('User deleted');
  } catch (e) {
    print('Error: $e');
  }
}

4. Handling Responses and Errors

Dio automatically throws a DioError for non-2xx status codes, so you can use a try-catch block to handle errors gracefully.

Future<void> fetchData() async {
  try {
    final response = await dio.get('/users');
    if (response.statusCode == 200) {
      // Handle successful response
      print(response.data);
    } else {
      // Handle other status codes
      print('Request failed with status: ${response.statusCode}');
    }
  } on DioError catch (e) {
    // Handle Dio-specific errors
    if (e.response != null) {
      print('Error response: ${e.response?.data}');
    } else {
      print('Error sending request: $e');
    }
  }
}

Conclusion

The dio package is a powerful tool for handling networking in Flutter. It simplifies making HTTP requests and provides advanced features like interceptors and error handling out of the box. By following this guide, you should now have a solid understanding of how to use dio in your Flutter projects.

📚 Resources

Happy coding! 🚀