Bài thực hành Dart http CRUD
Trong bài thực hành này chúng ta sẽ sử dụng gói http để gửi các yêu cầu tạo, cập nhập và xoá các bản ghi tới máy chủ. Và sử dụng gói dart:convert để chuyển đổi JSON thành đối tượng Dart và ngược lại.
2. CRUD Demo Server
Trước hết hãy đảm bảo rằng bạn đã triển khai CrudDemoServer, một máy chủ REST miễn phí được sử dụng trong các ví dụ của bài thực hành này.
3. Model
Các lớp Dart tham gia trong các ví dụ của bài học này.
model.dart
import 'dart:convert';
class ProductData {
int id;
String name;
bool active;
double price;
double estimatedInputPrice;
double taxRate;
ImageData? image;
CategoryData category;
ProductData({
required this.id,
required this.name,
required this.active,
required this.price,
required this.estimatedInputPrice,
required this.taxRate,
required this.image,
required this.category,
});
static ProductData fromMap(Map<String, dynamic> map) {
Map<String, dynamic> imgMap = map['image'];
return ProductData(
id: map['id'],
name: map['name'],
active: map['active'],
price: toDouble(map['price']),
estimatedInputPrice: toDouble(map['estimatedInputPrice']),
taxRate: toDouble(map['taxRate']),
image: imgMap == null ? null : ImageData.fromMap(imgMap),
category: CategoryData.fromMap(map['category']),
);
}
static ProductData fromJsonString(String jsonString) {
Map<String, dynamic> map = jsonDecode(jsonString);
return fromMap(map);
}
}
class CategoryData {
int id;
String name;
CategoryData({required this.id, required this.name});
static CategoryData fromMap(Map<String, dynamic> map) {
return CategoryData(id: map['id'], name: map['name']);
}
}
class ImageData {
int id;
String ext;
int width;
int height;
int size;
ImageData({
required this.id,
required this.ext,
required this.width,
required this.height,
required this.size,
});
static ImageData fromMap(Map<String, dynamic> map) {
return ImageData(
id: map['id'],
ext: map['ext'],
width: map['width'],
height: map['height'],
size: map['size'],
);
}
}
double toDouble(dynamic v) {
if (v is int) {
return v.toDouble();
} else if (v is double) {
return v;
}
throw Exception('Can not convert $v to double');
}
4. Api Model
api_model.dart
import 'dart:convert';
typedef Converter<D> = D Function(String jsonString);
typedef ErrorConverter = String Function(String jsonString);
class Result<D> {
D? data;
String? errorMessage;
Result({this.data, this.errorMessage});
}
/// json : '{"errorMessage":"Some Error!"}';
String defaultErrorConverter(String json) {
try {
Map<String,dynamic> map = jsonDecode(json);
var errorMessage = map['errorMessage'];
return errorMessage??json;
} catch(e) {
return json;
}
}
Lớp Result<D> mô phỏng một kết quả được từ việc gửi yêu cầu tới máy chủ.
D data | Đây là một đối tượng Dart đại diện cho dữ liệu mà bạn nhận được từ máy chủ. Trong thực tế máy chủ trả về cho bạn một văn bản JSON và bạn cần cung cấp một hàm để chuyển đổi JSON thành đối tượng này. |
errorMessage | Một văn bản mô tả nguyên nhân lỗi. Nếu thuộc tính này có giá trị null có nghĩa là không có lỗi gì xẩy ra. |
5. POST Utils
Một hàm tiện ích gửi một yêu cầu tới máy chủ để tạo một tài nguyên.
post_utils.dart
import 'package:http/http.dart' as http;
import 'api_model.dart';
Future<Result<D>> postData<D>({
required String apiUrl,
Object? body,
Map<String, String>? headers,
required Converter<D> converter,
ErrorConverter? errorConverter,
bool showDebug = false,
}) async {
D? data;
String? errorMessage;
try {
Uri url = Uri.parse(apiUrl);
final response = await http.post(
url,
headers: headers,
body: body,
);
String jsonString = response.body;
if (showDebug) {
print("Request Status Code: ${response.statusCode}");
print("JSON String: $jsonString");
}
if (response.statusCode == 201 || response.statusCode == 200) {
data = converter(jsonString);
} else {
if (errorConverter != null) {
errorMessage = errorConverter(jsonString);
} else {
errorMessage = jsonString;
}
}
} catch (e) {
errorMessage = e.toString();
}
return Result(errorMessage: errorMessage, data: data);
}
body | Dữ liệu được đính kèm trong yêu cầu để gửi tới máy chủ. |
headers | Thông tin headers, được gửi kèm trong yêu cầu tới máy chủ. Nó có thể bao gồm thông tin uỷ quyền (authorization) để đảm bảo người dùng có quyền hành động với các tài nguyên máy chủ.
|
converter | Trong trường hợp không có lỗi xẩy ra, máy chủ trả về một văn bản JSON. Hàm này được sử dụng để chuyển đổi văn bản JSON này thành đối tượng Dart <D>. |
errorConverter | Trong trường hợp có lỗi xẩy ra tại, máy chủ trả về một văn bản mang thông tin lỗi, nó có thể là một văn bản JSON. Hàm này chuyển đổi văn bản trên thành một thông điệp lỗi thân thiện với người dùng.
|
6. POST Example
Trong ví dụ này chúng ta sẽ gửi một yêu cầu tới máy chủ để tạo một Product.
main_post_demo.dart
import 'dart:convert';
import 'api_model.dart';
import 'model.dart';
import 'post_utils.dart';
Future<void> main() async {
// Public API (No login or Authentication Token required).
String apiUrl = "http://localhost:8080/public/rest/product/create";
// body must by Map<String,String>, not Map<String,dynamic>.
Map<String, String> body = {
"name": "Test Product",
"active": true.toString(),
"price": 20.toString(),
"estimatedInputPrice": 18.toString(),
"taxRate": 0.1.toString(),
"categoryId": 1.toString(),
};
// Authentication Token required if API is not public.
// var headers = <String, String>{
// 'Authorization': 'Basic Your-Basic-Token',
// };
var headers = <String, String>{};
Result<ProductData> result = await postData(
apiUrl: apiUrl,
headers: headers,
body: body,
converter: ProductData.fromJsonString,
errorConverter: defaultErrorConverter,
showDebug: true,
);
if (result.errorMessage != null) {
print(result.errorMessage);
} else {
ProductData product = result.data!;
print('Product: ${product.id}');
}
}
Sau khi chạy ví dụ bạn sẽ thấy một bản ghi được tạo ra trên bảng PRODUCT.
7. PUT Utils
Một hàm tiện ích để gửi một yêu cầu cập nhập một tài nguyên trên máy chủ.
put_utils.dart
import 'package:http/http.dart' as http;
import 'api_model.dart';
Future<Result<D>> putData<D>({
required String apiUrl,
Object? body,
Map<String, String>? headers,
required Converter<D> converter,
ErrorConverter? errorConverter,
bool showDebug = false,
}) async {
D? data;
String? errorMessage;
try {
Uri url = Uri.parse(apiUrl);
final response = await http.put(
url,
headers: headers,
body: body,
);
String jsonString = response.body;
if (showDebug) {
print("Request Status Code: ${response.statusCode}");
print("JSON String: $jsonString");
}
if (response.statusCode == 200) {
data = converter(jsonString);
} else {
if (errorConverter != null) {
errorMessage = errorConverter(jsonString);
} else {
errorMessage = jsonString;
}
}
} catch (e) {
errorMessage = e.toString();
}
return Result(errorMessage: errorMessage, data: data);
}
8. PUT Example
Trong ví dụ này chúng ta sẽ gửi một yêu cầu tới máy chủ để cập nhập một PRODUCT.
main_put_demo.dart
import 'api_model.dart';
import 'model.dart';
import 'put_utils.dart';
Future<void> main() async {
// Public API (No login or Authentication Token required).
String apiUrl = "http://localhost:8080/public/rest/product/update";
// body must by Map<String,String>, not Map<String,dynamic>.
Map<String, String> body = {
"id": 1.toString(),
"name": "333 Beer (Update)", // <== Update Name.
"active": true.toString(),
"price": 1.toString(),
"estimatedInputPrice": 0.8.toString(),
"taxRate": 0.1.toString(),
"categoryId": 1.toString(),
};
// Authentication Token required if API is not public.
// var headers = <String, String>{
// 'Authorization': 'Basic Your-Basic-Token',
// };
var headers = <String, String>{};
Result<ProductData> result = await putData(
apiUrl: apiUrl,
headers: headers,
body: body,
converter: ProductData.fromJsonString,
errorConverter: defaultErrorConverter,
showDebug: true,
);
if (result.errorMessage != null) {
print(result.errorMessage);
} else {
ProductData product = result.data!;
print('Product: ${product.id}');
}
}
9. DELETE Utils
Một hàm tiện ích để gửi yêu cầu xoá một tài nguyên trên máy chủ.
delete_utils.dart
import 'package:http/http.dart' as http;
import 'api_model.dart';
Future<Result<void>> deleteData<D>({
required String apiUrl,
Object? body,
Map<String, String>? headers,
ErrorConverter? errorConverter,
bool showDebug = false,
}) async {
String? errorMessage;
try {
Uri url = Uri.parse(apiUrl);
final response = await http.delete(
url,
headers: headers,
body: body,
);
String jsonString = response.body;
if (showDebug) {
print("Request Status Code: ${response.statusCode}");
print("JSON String: $jsonString");
}
if (response.statusCode == 200) {
// Nothing to do.
} else {
if (errorConverter != null) {
errorMessage = errorConverter(jsonString);
} else {
errorMessage = jsonString;
}
}
} catch (e) {
errorMessage = e.toString();
}
return Result(errorMessage: errorMessage, data: null);
}
10. DELETE Example
Trong ví dụ này chúng ta sẽ tạo một yêu cầu xoá một PRODUCT.
main_delete_demo.dart
import 'api_model.dart';
import 'delete_utils.dart';
Future<void> main() async {
// Public API (No login or Authentication Token required).
String apiUrl = "http://localhost:8080/public/rest/product/delete/19";
// body must by Map<String,String>, not Map<String,dynamic>.
Map<String, String> body = {};
// Authentication Token required if API is not public.
// var headers = <String, String>{
// 'Authorization': 'Basic Your-Basic-Token',
// };
var headers = <String, String>{};
Result<void> result = await deleteData(
apiUrl: apiUrl,
headers: headers,
body: body,
errorConverter: defaultErrorConverter,
showDebug: true,
);
if (result.errorMessage != null) {
print(result.errorMessage);
} else {
print('Successful!');
}
}
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