Hướng dẫn và ví dụ Dart Dio
Dio là một thư viện HTTP Client mạnh mẽ cho Dart/Flutter. Dio được xây dựng phía trên gói http tiêu chuẩn của Dart, với các tính năng bổ xung khiến nó trở lên mạnh và linh hoạt hơn:
- Interceptors
- Request cancellation
- Request Retry
Các tham số được sử dụng trong các phương thức của lớp Dio và mô tả của chúng:
queryParameters | Chỉ định các "Query parameters" (Tham số truy vấn) bao gồm trong URL của yêu cầu. |
options |
|
data | Chỉ định dữ liệu bao gồm trong phần thân của yêu cầu. Kiểu dữ liệu có thể là:
|
cancelToken | Một đối tượng được sử dụng để huỷ yêu cầu. Khi yêu cầu bị huỷ CancelTokenException sẽ được ném ra.
|
onSendProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được gửi đi. Hàm này có ích trong trường hợp upload dữ liệu có dung lượng lớn.
|
onReceiveProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được tải về. Hàm này có ích trong trường hợp downoad dữ liệu có dung lượng lớn.
|
Trong bài viết này chúng ta sẽ tìm hiểu về các tính năng cơ bản của gói Dio, các tính năng nâng cao sẽ được đề xuất trong các bài viết tách biệt ở cuối bài viết này.
2. CrudDemoServer
Bài học này sử dụng một máy chủ mô phỏng CrudDemoServer. Bạn có thể download và cài đặt miễn phí theo liên kết dưới đây:
Sau khi đăng nhập thành công vào CrudDemoServer bạn sẽ nhận được một accessToken. Để có thể truy vấn, thêm, xoá và sửa các tài nguyên trên CrudDemoServer bạn cần đính kèm accessToken vào các yêu cầu.
_constants.dart
import 'dart:convert';
///
/// After successfully logging in, you will have accessToken.
/// Here is an example accessToken,
/// used for the examples in this lesson.
///
/// For example: YWRtaW46MTIz
///
String get accessToken {
String userName = "admin";
String password = "123";
String str = "$userName:$password";
final bytes = utf8.encode(str);
// YWRtaW46MTIz
final base64Str = base64.encode(bytes);
return base64Str;
}
3. Dio Constructor
Lớp Dio chỉ có một constructor duy nhất với một tham số tuỳ chọn.
Dio([BaseOptions? options])
Constructor của lớp BaseOptions:
BaseOptions({
String? method,
Duration? connectTimeout,
Duration? receiveTimeout,
Duration? sendTimeout,
String baseUrl = '',
Map<String, dynamic>? queryParameters,
Map<String, dynamic>? extra,
Map<String, dynamic>? headers,
bool? preserveHeaderCase = false,
ResponseType? responseType = ResponseType.json,
String? contentType,
bool Function(int?)? validateStatus,
bool? receiveDataWhenStatusError,
bool? followRedirects,
int? maxRedirects,
bool? persistentConnection,
FutureOr<List<int>> Function(String, RequestOptions)? requestEncoder,
FutureOr<String?> Function(List<int>, RequestOptions, ResponseBody)? responseDecoder,
ListFormat? listFormat,
});
4. Tạo đối tượng Dio
Tạo một đối tượng Dio mặc định:
dio_ex1.dart
import 'package:dio/dio.dart';
// Create a Dio object:
final dio = Dio();
Future<void> main() async {
var path =
"https://raw.githubusercontent.com/o7planning/rs/master/dart/json/user-info-1.json";
final response = await dio.get(path);
print(response.data);
}
Output:
{
"userName": "tom",
"fullName": "Tom Cat",
"country": "America"
}
Dio(BaseOptions):
Ví dụ tiếp theo này, chúng ta sẽ tạo một đối tượng Dio với các tuỳ chọn cơ sở như baseUrl, connectTimeout, receiveTimeout và headers.
connectTimeout | Thời gian tối đa chờ đợi kết nối, nếu quá thời gian này kết nối coi như bị thất bại. |
receiveTimeout | Thời gian tối đa chờ đợi kết quả trả về từ máy chủ, nếu vượt quá thời gian này yêu cầu được coi là thất bại. |
dio_ex2.dart
import 'package:dio/dio.dart';
// Create a Dio object with Base Options :
final dio = Dio(
BaseOptions(
baseUrl: 'https://raw.githubusercontent.com',
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 5),
headers: {
'Accept': 'application/json',
},
),
);
Future<void> main() async {
// url = baseUrl + path
var path = "/o7planning/rs/master/dart/json/user-info-1.json";
final response = await dio.get(path);
print(response.data);
}
Sau khi tạo được đối tượng Dio với các tuỳ chọn cơ sở bạn có thể sử dụng nó để gửi các yêu cầu khác nhau tới máy chủ như GET, POST, PUT, PATCH và DELETE. Về cơ bản, bạn có thể chỉ cần tạo một đối tượng Dio và sử dụng nó nhiều lần cho nhiều loại yêu cầu khác nhau.
5. Dio GET
Phương thức get() của lớp Dio được sử dụng để gửi một yêu cầu GET tới máy chủ để nhận về một tài nguyên.
dio.get()
Future<Response<T>> get<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
void Function(int, int)? onReceiveProgress,
});
queryParameters | Chỉ định các "Query parameters" (Tham số truy vấn) bao gồm trong URL của yêu cầu. |
data | Chỉ định dữ liệu bao gồm trong phần thân của yêu cầu. Kiểu dữ liệu có thể là:
|
cancelToken | Một đối tượng được sử dụng để huỷ yêu cầu. Khi yêu cầu bị huỷ CancelTokenException sẽ được ném ra.
|
onReceiveProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được tải về. Hàm này có ích trong trường hợp downoad dữ liệu có dung lượng lớn.
|
6. Dio GET Example
Ví dụ đơn giản, sử dụng Dio để gửi một yêu cầu GET tới máy chủ.
dio_get_ex1.dart
import 'package:dio/dio.dart';
import '_constants.dart';
// Create a Dio object with Base Options :
final dio = Dio(
BaseOptions(
// Please download and Install CrudDemoServer.
baseUrl: 'http://localhost:8080',
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 5),
headers: {
'Accept': 'application/json',
},
),
);
Future<void> main() async {
Map<String, dynamic> headers = {
'Authorization': 'Basic $accessToken', // <-----
};
//
try {
final response = await dio.get(
'/rest/appUsers/search',
options: Options(headers: headers),
queryParameters: {
'searchText': 'anony',
'page': 1,
},
);
// response.data ==> Map<String,dynamic> or List<dynamic>
Map<String, dynamic> data = response.data;
print(data);
} on DioException catch (e) {
if (e.response != null) {
// Handle error response
print('Error 01: ${e.response!.statusCode}: ${e.response!.statusMessage}');
// e.response.data ==> Map<String,dynamic> or List<dynamic> or String.
var errorData = e.response!.data;
print("Error Data: $errorData");
} else {
// Handle no response
print('Error 02: ${e.message}');
}
}
}
Output:
{currentPage: 1, elements:
[{activated: true, email: anonymous1@example.com, enabled: true, fullName: Anonymous 1, id: 10,
image: {id: 10, ext: png, size: 16805, width: 128, height: 128}, userName: anonymous1},
{activated: true, email: anonymous2@example.com, enabled: true, fullName: Anonymous 2, id: 11,
image: {id: 11, ext: png, size: 7901, width: 128, height: 128}, userName: anonymous2},
{activated: true, email: anonymous3@example.com, enabled: true, fullName: Anonymous 3, id: 12,
image: {id: 12, ext: png, size: 9139, width: 128, height: 128}, userName: anonymous3}],
pageSize: 10, totalElements: 3, totalPages: 1}
Bạn có thể chạy lại ví dụ trên với một đường dẫn không tồn tại và xem kết quả.
- path = '/rest/appUsers/search-XX'
Error 01: 400:
Error Data: {type: about:blank, title: Bad Request, status: 400, detail: Failed to convert 'page' with value: 'search-XX', instance: /rest/appUsers/search-XX}
7. Dio POST
Phương thức post() của lớp Dio được sử dụng để gửi yêu cầu POST đến máy chủ nhằm tạo tài nguyên.
post()
Future<Response<T>> post<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
void Function(int, int)? onSendProgress,
void Function(int, int)? onReceiveProgress,
});
queryParameters | Chỉ định các "Query parameters" (Tham số truy vấn) bao gồm trong URL của yêu cầu. |
data | Chỉ định dữ liệu bao gồm trong phần thân của yêu cầu. Kiểu dữ liệu có thể là:
|
cancelToken | Một đối tượng được sử dụng để huỷ yêu cầu. Khi yêu cầu bị huỷ CancelTokenException sẽ được ném ra.
|
onSendProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được gửi đi. Hàm này có ích trong trường hợp upload dữ liệu có dung lượng lớn.
|
onReceiveProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được tải về. Hàm này có ích trong trường hợp downoad dữ liệu có dung lượng lớn.
|
8. Dio POST Example
New fragment 1414264
dio_post_ex.dart
import 'package:dio/dio.dart';
import '_constants.dart';
// Create a Dio object with Base Options :
final dio = Dio(
BaseOptions(
// Please download and Install CrudDemoServer.
baseUrl: 'http://localhost:8080',
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 5),
headers: {
'Accept': 'application/json',
},
),
);
Future<void> main() async {
Map<String, dynamic> headers = {
'Authorization': 'Basic $accessToken', // <-----
};
//
Map<String, dynamic> mapData = {
"name": "Test Product",
"active": true,
"price": 20,
"estimatedInputPrice": 18,
"taxRate": 0.1,
"categoryId": 1,
};
var formData = FormData.fromMap(mapData);
//
try {
final response = await dio.post(
'/rest/product/create',
options: Options(headers: headers),
data: formData, // FormData
);
// response.data ==> Map<String,dynamic> or List<dynamic>
Map<String, dynamic> data = response.data;
print(data);
} on DioException catch (e) {
if (e.response != null) {
// Handle error response
print(
'Error 01: ${e.response!.statusCode}: ${e.response!.statusMessage}');
// e.response.data ==> Map<String,dynamic> or List<dynamic> or String.
var errorData = e.response!.data;
print("Error Data: $errorData");
} else {
// Handle no response
print('Error 02: ${e.message}');
}
}
}
Output:
{active: true, category: {id: 1, name: Alcoholic drink},
estimatedInputPrice: 18, id: 19, imageSize: 0,
name: Test Product, price: 20, taxRate: 0.1}
- Flutter upload ảnh sử dụng Dio và ImagePicker
Gửi yêu cầu POST với file đính kèm:
Map<String, dynamic> mapData = {
"name": "Test Product",
"active": true,
"price": 20,
"estimatedInputPrice": 18,
"taxRate": 0.1,
"categoryId": 1,
"imageFileUpload": await MultipartFile.fromFile(
'/path/to/product.jpg',
filename: 'product.jpg',
),
};
var formData = FormData.fromMap(mapData);
9. Dio PUT
Phương thức put() của lớp Dio được sử dụng để gửi một yêu cầu PUT tới máy chủ để cập nhập một tài nguyên nào đó.
put()
Future<Response<T>> put<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
void Function(int, int)? onSendProgress,
void Function(int, int)? onReceiveProgress,
});
queryParameters | Chỉ định các "Query parameters" (Tham số truy vấn) bao gồm trong URL của yêu cầu. |
data | Chỉ định dữ liệu bao gồm trong phần thân của yêu cầu. Kiểu dữ liệu có thể là:
|
cancelToken | Một đối tượng được sử dụng để huỷ yêu cầu. Khi yêu cầu bị huỷ CancelTokenException sẽ được ném ra.
|
onSendProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được gửi đi. Hàm này có ích trong trường hợp upload dữ liệu có dung lượng lớn.
|
onReceiveProgress | Một hàm callback được gọi trong quá trình dữ liệu đang được tải về. Hàm này có ích trong trường hợp downoad dữ liệu có dung lượng lớn.
|
10. Dio PUT Example
dio_put_ex1.dart
import 'package:dio/dio.dart';
import '_constants.dart';
// Create a Dio object with Base Options :
final dio = Dio(
BaseOptions(
// Please download and Install CrudDemoServer.
baseUrl: 'http://localhost:8080',
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 5),
headers: {
'Accept': 'application/json',
},
),
);
Future<void> main() async {
Map<String, dynamic> headers = {
'Authorization': 'Basic $accessToken', // <-----
};
//
Map<String, dynamic> mapData = {
"id": 1,
"name": "333 Beer (Update)", // <== Update Name.
"active": true,
"price": 1,
"estimatedInputPrice": 0.8,
"taxRate": 0.1,
"categoryId": 1,
};
var formData = FormData.fromMap(mapData);
//
try {
final response = await dio.put(
'/rest/product/update',
options: Options(headers: headers),
data: formData, // FormData
);
// response.data ==> Map<String,dynamic> or List<dynamic>
Map<String, dynamic> data = response.data;
print(data);
} on DioException catch (e) {
if (e.response != null) {
// Handle error response
print(
'Error 01: ${e.response!.statusCode}: ${e.response!.statusMessage}');
// e.response.data ==> Map<String,dynamic> or List<dynamic> or String.
var errorData = e.response!.data;
print("Error Data: $errorData");
} else {
// Handle no response
print('Error 02: ${e.message}');
}
}
}
- Flutter upload ảnh sử dụng Dio và ImagePicker
Gửi yêu cầu PUT với file đính kèm:
Map<String, dynamic> mapData = {
"id": 1.toString(),
"name": "333 Beer (Update)", // <== Update Name.
"active": true,
"price": 1,
"estimatedInputPrice": 0.8,
"taxRate": 0.1,
"categoryId": 1,
"imageFileUpload": await MultipartFile.fromFile(
'/path/to/product.jpg',
filename: 'product.jpg',
),
};
var formData = FormData.fromMap(mapData);
11. Dio DELETE
Phương thức delete() của lớp Dio được sử dụng để gửi một yêu cầu DELETE tới máy chủ để xoá các tài nguyên nào đó.
delete()
Future<Response<T>> delete<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
Options? options,
CancelToken? cancelToken,
});
queryParameters | Chỉ định các "Query parameters" (Tham số truy vấn) bao gồm trong URL của yêu cầu. |
cancelToken | Một đối tượng được sử dụng để huỷ yêu cầu. Khi yêu cầu bị huỷ CancelTokenException sẽ được ném ra.
|
data | Chỉ định dữ liệu bao gồm trong phần thân của yêu cầu. Kiểu dữ liệu có thể là:
|
12. Dio DELETE Example
dio_delete_ex1.dart
import 'package:dio/dio.dart';
import '_constants.dart';
// Create a Dio object with Base Options :
final dio = Dio(
BaseOptions(
// Please download and Install CrudDemoServer.
baseUrl: 'http://localhost:8080',
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 5),
headers: {
'Accept': 'application/json',
},
),
);
Future<void> main() async {
Map<String, dynamic> headers = {
'Authorization': 'Basic $accessToken', // <-----
};
//
try {
final response = await dio.delete(
'/rest/product/delete/19',
options: Options(headers: headers),
);
print("Done");
} on DioException catch (e) {
if (e.response != null) {
// Handle error response
print('Error: ${e.response!.statusCode}: ${e.response!.statusMessage}');
// e.response.data ==> Map<String,dynamic> or List<dynamic> or String.
var errorData = e.response!.data;
print("Error Data: $errorData");
} else {
// Handle no response
print('No Response Error: ${e.message}');
}
}
}
Các hướng dẫn lập trình Dart
- Kiểu dữ liệu Boolean trong Dart
- Hướng dẫn và ví dụ hàm trong Dart
- Hướng dẫn và ví dụ Dart Closures
- Interface trong Dart
- Hướng dẫn và ví dụ phương thức trong Dart
- Constructor trong Dart
- Property trong Dart
- Toán tử chấm chấm (..) trong Dart
- Hướng dẫn và ví dụ Dart Generics
- Lập trình Dart với công cụ trực tuyến DartPad
- Cài đặt Dart SDK trên Windows
- Cài đặt Visual Studio Code trên Windows
- Cài đặt Dart Code Extension cho Visual Studio Code
- Cài đặt Dart Plugin cho Android Studio
- Chạy ví dụ Dart đầu tiên của bạn trong Visual Studio Code
- Chạy ví dụ Dart đầu tiên của bạn trong Android Studio
- Dart JSON với thư viện dart:convert
- Hướng dẫn và ví dụ Dart List
- Biến (Variable) trong ngôn ngữ Dart
- Hướng dẫn và ví dụ Dart Map
- Vòng lặp trong Dart
- Xử lý Dart JSON với gói dart_json_mapper
- Trình chuyển đổi mã nguồn (Transpiler) là gì?
- Phân tích XML trong Dart
- Hướng dẫn và ví dụ Dart http
- Hướng dẫn và ví dụ Dart Future
- Các phương thức mở rộng (Extension) trong Dart
- Mixins trong Dart
- Bài thực hành Dart phân tích JSON với gói dart:convert
- Bài thực hành Dart http CRUD
- Từ khoá part và part of trong Dart
- Hướng dẫn và ví dụ Dart Dio
Show More