vn_provinces_api 1.0.2
vn_provinces_api: ^1.0.2 copied to clipboard
Flutter/Dart package để truy vấn dữ liệu địa chỉ tỉnh thành, phường xã Việt Nam qua provinces.open-api.vn.
vn_provinces_api #
Flutter/Dart package để truy vấn dữ liệu địa chỉ tỉnh thành, quận huyện, phường xã Việt Nam qua API provinces.open-api.vn.
Hỗ trợ API v2 (sau sáp nhập).
Tính năng #
- ✅ Lấy danh sách tỉnh/thành phố, phường/xã
- ✅ Tìm kiếm theo tên (có dấu hoặc không dấu)
- ✅ Hỗ trợ
depthđể lấy dữ liệu lồng nhau (province → ward) - ✅ Xử lý lỗi đầy đủ với các exception có nghĩa
- ✅ Hỗ trợ custom
http.Clientđể dễ dàng mock trong test - ✅ Null-safe, type-safe
Cài đặt #
dart pub add vn_provinces_api
Sử dụng cơ bản #
import 'package:vn_provinces_api/vn_provinces_api.dart';
void main() async {
// Mặc định dùng API v2 (sau sáp nhập 07/2025)
final client = VnProvincesClient();
// Lấy tất cả tỉnh thành
final provinces = await client.getProvinces();
print(provinces.first.name); // Thành phố Hà Nội
// Tìm kiếm tỉnh thành
final results = await client.searchProvinces('Hồ Chí Minh');
print(results.first.name); // Thành phố Hồ Chí Minh
client.dispose(); // Đóng kết nối khi xong
}
API Reference #
Khởi tạo #
final client = VnProvincesClient();
// Tùy chỉnh timeout
final client = VnProvincesClient(timeout: Duration(seconds: 15));
Tỉnh / Thành phố #
| Phương thức | Mô tả |
|---|---|
getProvinces({depth}) |
Lấy danh sách tất cả tỉnh thành |
getProvince(code, {depth}) |
Lấy thông tin một tỉnh theo mã |
searchProvinces(q) |
Tìm kiếm tỉnh theo tên |
Phường / Xã / Thị trấn #
| Phương thức | Mô tả |
|---|---|
getWard(code) |
Lấy thông tin một phường/xã theo mã |
searchWards(q) |
Tìm kiếm phường/xã theo tên |
Tham số depth #
depth |
Dữ liệu trả về |
|---|---|
1 (mặc định) |
Chỉ cấp hiện tại |
2 |
Kèm cấp con (vd: province + wards) |
Xử lý lỗi #
try {
final province = await client.getProvince(9999);
} on VnProvincesNotFoundException catch (e) {
print('Không tìm thấy: ${e.message}');
} on VnProvincesNetworkException catch (e) {
print('Lỗi mạng: ${e.message}');
} on VnProvincesHttpException catch (e) {
print('Lỗi HTTP ${e.statusCode}: ${e.message}');
} on VnProvincesException catch (e) {
print('Lỗi khác: ${e.message}');
}
Danh sách exceptions #
| Exception | Khi nào |
|---|---|
VnProvincesNotFoundException |
Mã không tồn tại (404) |
VnProvincesNetworkException |
Mất mạng, timeout |
VnProvincesHttpException |
Lỗi HTTP khác (4xx, 5xx) |
VnProvincesParseException |
JSON không hợp lệ |
Ví dụ: Dropdown chọn địa chỉ 2 cấp #
class AddressPicker extends StatefulWidget { ... }
class _AddressPickerState extends State<AddressPicker> {
final client = VnProvincesClient();
Province? selectedProvince;
Ward? selectedWard;
@override
Widget build(BuildContext context) {
return Column(
children: [
// Dropdown tỉnh/thành
FutureBuilder<List<Province>>(
future: client.getProvinces(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
return DropdownButton<Province>(
value: selectedProvince,
items: snapshot.data!
.map((p) => DropdownMenuItem(value: p, child: Text(p.name)))
.toList(),
onChanged: (p) async {
setState(() => selectedProvince = p);
final full = await client.getProvince(p!.code, depth: 2);
// dùng full.wards cho dropdown tiếp theo
},
);
},
),
// ... dropdown phường/xã tương tự
],
);
}
}
Testing #
Package hỗ trợ inject http.Client để mock dễ dàng:
import 'package:mockito/mockito.dart';
import 'package:http/http.dart' as http;
class MockClient extends Mock implements http.Client {}
final mockClient = MockClient();
final client = VnProvincesClient(httpClient: mockClient);
when(mockClient.get(any)).thenAnswer(
(_) async => http.Response('[{"name":"Hà Nội","code":1,...}]', 200),
);
final provinces = await client.getProvinces();
expect(provinces.first.name, 'Hà Nội');
Chạy test:
flutter test
Data source #
API được cung cấp bởi provinces.open-api.vn, dựa trên thư viện VietnamProvinces của Nguyễn Hồng Quân. Hosting được tài trợ bởi OMZCloud.
Vui lòng không lạm dụng API công cộng — đặc biệt tham số depth=3.
License #
MIT