Flutter: ô tự động hoàn thành địa chỉ Việt Nam (suggest + resolve)
Dựng ô nhập địa chỉ Việt Nam trong Flutter: debounce, gọi /v1/suggest gợi ý và /v1/place/resolve lấy toạ độ, proxy giấu API key — kèm code Dart đầy đủ.
Gần như mọi app giao hàng, đặt xe hay dịch vụ tại nhà ở Việt Nam đều cần một ô
nhập địa chỉ thông minh: người dùng gõ vài chữ, app gợi ý đúng địa chỉ, và khi
chọn xong bạn có ngay toạ độ để đặt ghim hay tính quãng đường. Bài này dựng
ô đó trong Flutter, ghép hai endpoint của GoGoDuk — /v1/suggest
để gợi ý và /v1/place/resolve để lấy toạ độ
chuẩn cho địa chỉ người dùng chọn — với code Dart chạy được.
Nếu bạn làm web React/Next.js, xem bản đối chiếu cùng kiến trúc trong bài Component autocomplete địa chỉ cho React/Next.js. Bài này là phiên bản mobile/Dart của cùng ý tưởng.
Vì sao app mobile Việt Nam cần autocomplete địa chỉ riêng
Địa chỉ Việt Nam viết theo nhiều kiểu: có dấu, không dấu, "Q.1" hay "Quận 1", "P. Bến Nghé", số nhà kèm hẻm. Một ô tìm địa chỉ tốt phải khớp được những biến thể đó và trả về dạng chuẩn. Tự dựng danh sách địa chỉ trong app gần như bất khả thi; gọi một API geocoding tối ưu cho Việt Nam thì gọn hơn nhiều.
Cách nhiều người làm sai là đặt một TextField rồi gọi thẳng API mỗi lần gõ
phím. Ba vấn đề hay gặp:
- Lộ API key. Nhúng
X-API-Keythẳng trong app Dart nghĩa là bất kỳ ai decompile APK/IPA hoặc xem traffic đều lấy được key của bạn. - Không debounce. Gõ nhanh tạo ra hàng loạt request đua nhau, kết quả nhảy loạn và tốn quota.
- Không gộp phiên billing. Mỗi lần gõ là một request rời, không nối thành một phiên "gõ → chọn" duy nhất.
Kiến trúc: app → proxy → GoGoDuk
Quy tắc vàng cho mobile: API key không bao giờ nằm trong app. App gọi tới
backend proxy của chính bạn; proxy mới gắn X-API-Key và gọi GoGoDuk.
Đây cũng đúng kiến trúc bài React dùng — chỉ khác phần client là Dart thay vì JavaScript. Proxy có thể là bất kỳ backend nào bạn đang có (Node, Go, Firebase Cloud Functions…); nó chỉ cần forward query và đính kèm key.
Bước 1: client Dart gọi suggest qua proxy
Endpoint /v1/suggest cần input tối thiểu 2 ký tự, nhận lang (mặc định
vi), country (chỉ VN), và tuỳ chọn focus.lat/focus.lon để ưu tiên kết
quả gần một vị trí. Mỗi phản hồi trả về mảng predictions, mỗi phần tử có
placeId, text, mainText, secondaryText.
Phía proxy chỉ cần forward các query này tới https://api.gogoduk.com/v1/suggest
kèm header X-API-Key. Logic giống hệt route proxy trong bài React — chỉ là
ngôn ngữ backend của bạn.
Bước 2: TextField + debounce + dropdown
Trong Flutter, ta bọc một TextField bằng một Timer để debounce ~300ms:
chỉ gọi suggest khi người dùng ngừng gõ, tránh bắn request mỗi ký tự. Một
sessionToken duy nhất cho mỗi phiên (gõ → chọn) giúp gộp billing.
Bước 3: resolve placeId thành toạ độ
predictions chỉ có placeId, chưa có toạ độ. Khi người dùng chọn một gợi ý,
gọi /v1/place/resolve với id là placeId
đó (truyền cùng sessionToken để đóng phiên billing). Phản hồi result có
lat, lon, name, address, và district/city (có thể null).
Bây giờ trong onSelected của AddressField, bạn có toạ độ để đặt ghim trên
bản đồ, lưu vào đơn hàng, hay tính phí ship theo quãng đường.
Lưu ý khi đưa lên production
- Tuyệt đối không nhúng API key trong app. APK/IPA decompile được; key trong binary coi như công khai. Luôn đi qua proxy server-side.
- Gộp session billing. Dùng một
sessionTokencho cả phiên "gõ → chọn", đổi token mới sau khi resolve. Suggest và resolve cùng token được tính là một phiên. - Debounce + huỷ request cũ. 250–300ms là hợp lý cho mobile. Nhớ
cancel()timer trongdispose()để tránhsetStatesau khi widget đã unmount. focus.lat/focus.lon. Nếu đã có GPS của người dùng, truyền vào suggest để ưu tiên địa chỉ gần họ — gợi ý chính xác hơn hẳn.- Xử lý lỗi & rỗng. Mạng mobile chập chờn; luôn có nhánh cho
predictionsrỗng và lỗi HTTP, đừng để dropdown treo.
Khi nào dùng SDK, khi nào gọi raw
GoGoDuk có SDK TypeScript bọc sẵn suggest và placeResolve — tiện nếu
backend proxy của bạn viết bằng Node/TS. Nhưng phía app Dart thì không gọi
GoGoDuk trực tiếp (vì phải giấu key), nên client luôn nói chuyện với proxy của
bạn qua HTTP thuần như trên. Nói cách khác: SDK (nếu dùng) nằm ở tầng proxy, còn
Flutter chỉ cần http.
Nếu app của bạn cần đi từ toạ độ GPS ra tỉnh/huyện/xã (ví dụ app tài xế), xem thêm reverse geocoding xác định tỉnh/huyện từ toạ độ và bài tổng quan Geocoding là gì. Còn về cách hệ thống autocomplete địa chỉ Việt Nam hoạt động, xem Vietnam Address Autocomplete API.
Kết luận
Một ô autocomplete địa chỉ tốt trong Flutter chỉ cần ba mảnh ghép: debounce để gõ mượt, proxy để giấu key, và cặp suggest + resolve để biến vài chữ người dùng gõ thành một toạ độ chuẩn. Kiến trúc giống hệt bản web, nên nếu team bạn làm cả web lẫn mobile thì cùng một backend proxy phục vụ được cả hai.
Tạo API key miễn phí ở app.gogoduk.com để bắt đầu, đọc chi tiết hai endpoint tại docs suggest và docs place resolve. Có thắc mắc hay cần review kiến trúc? Tham gia cộng đồng dev trên Telegram.
Muốn dùng GoGoDuk?
Miễn phí trọn đời — 100 request/ngày mỗi tài khoản, không cần thẻ tín dụng. Giới hạn cao hơn theo yêu cầu.
Đăng ký →