Интеграция сервиса DaData для подсказок адресов в мобильном приложении
Google Places Autocomplete хорошо работает в Европе и США. В России — хуже: незнакомые корпуса, строения вида «1А», адреса в промзонах, садовые товарищества. DaData решает именно это: их база построена на ФИАС/КЛАДР и знает адресное пространство России значительно глубже.
Что интегрируем
Основной эндпоинт для подсказок при вводе: POST https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address. Тело запроса — JSON с полем query (введённая строка) и опциональным locations для ограничения по региону. Ответ содержит массив suggestions, каждый с полями value (полный адрес), data.geo_lat, data.geo_lon, data.house, data.street, data.city_with_type.
Второй эндпоинт — геокодирование по координатам: POST .../geolocate/address с lat/lon и radius_meters. Удобно как fallback к Google Reverse Geocoding для российских адресов.
Реализация на iOS
Создаём DaDataService с URLSession или Alamofire. Авторизация через заголовок Authorization: Token <API_KEY>. Ключ храним в xcconfig и читаем через Bundle.main.infoDictionary — не хардкодим в коде.
Подсказки показываем в UITableView под текстовым полем. Запросы дебаунсируем через Combine: searchSubject.debounce(for: .milliseconds(300), scheduler: RunLoop.main). Без дебаунса при быстром вводе улетает по запросу на каждый символ.
Пример обработки ответа:
struct DaDataSuggestion: Decodable {
let value: String
let data: DaDataAddress
}
struct DaDataAddress: Decodable {
let geoLat: String?
let geoLon: String?
let city: String?
let street: String?
let house: String?
enum CodingKeys: String, CodingKey {
case geoLat = "geo_lat"
case geoLon = "geo_lon"
case city, street, house
}
}
Важно: geo_lat и geo_lon приходят как String, не Double. Конвертируем через Double(geoLat ?? "") с проверкой на nil.
Реализация на Android
Retrofit-интерфейс с @POST и @Header("Authorization"). Корутина в ViewModel, StateFlow<List<DaDataSuggestion>> для UI. Дебаунс через Flow.debounce(300) в collectLatest.
В compose-проекте LazyColumn под TextField с DropdownMenuItem или кастомным Popup. Тут важно правильно управлять фокусом: при выборе подсказки убираем фокус с поля через LocalFocusManager.current.clearFocus() и скрываем клавиатуру через LocalSoftwareKeyboardController.
Flutter
Пакета под DaData нет в pub.dev с нормальным рейтингом — пишем свой DaDataRepository с Dio. Подсказки отдаём через StreamController с дебаунсом Timer(Duration(milliseconds: 300), ...). Для UI — ListView.builder в Overlay или пакет flutter_typeahead с кастомным suggestionsCallback.
Важные нюансы
Квота на бесплатном плане — 10 000 запросов в день. Для приложений с активной аудиторией этого не хватит с первой недели. Учитывайте квоту при выборе тарифа ещё на этапе архитектуры.
При первичной загрузке страницы — не запрашивать подсказки для пустой строки, это тратит квоту без пользы. Минимальная длина запроса — 3 символа.
Срок интеграции: один-два дня. Включает клиентский сервис, UI-компонент с дебаунсом, обработку выбора адреса и маппинг координат.







