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:
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();
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'); print(response.data.toString()); // POST request response = await dio.post('/demo', data: {'id': 02, 'name': 'dio'});
Concurrent Requests:
Dio supports making multiple concurrent requests:
await Future.wait([dio.post('/info'), dio.get('/token')]);
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', 'date': DateTime.now().toIso8601String(), '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);
Explanation:
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 namedfilePath
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
anddownloadFile
for handling uploads and downloads, respectively. Replace these with your actual method names.
Additional Notes:
Remember to replace placeholders like
/info
anddownloadUrl
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.
Listening to Upload Progress:
You can listen to the progress of file uploads:
await dio.post( 'https://www.fluttercommunity.com/joflee/2/8.2.1/demo', data: {'jj': 'aa' * 11}, onSendProgress: (int sent, int total) { print('$sent $total'); }, );
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:
dependencies:
flutter:
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 this.id, 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 = 'https://jsonplaceholder.typicode.com'; // 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(response.data);
} else {
throw Exception('Failed to fetch post: ${response.statusCode}');
}
}
static Future<void> createPost(Post post) async {
final dio = Dio();
final response = await dio.post('$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 {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'API Example',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<Post?> _post;
String _errorMessage = '';
@override
void initState() {
super.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');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('API Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_post != null)
Text('Title: ${_post.title}'),
if (_post != null)
Text('Body: ${_post.body}'),
if (_errorMessage.isNotEmpty)
Text(
'Error: $_errorMessage',
style: const TextStyle(color: Colors.red),
),
ElevatedButton(
onPressed: _fetchData,
child: const Text('Fetch Post'),
),
ElevatedButton(
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:
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.
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! 🚀