Оптимізація введення адреси: автодоповнення у мобільних застосунках

Оптимізація введення адреси: автодоповнення та кешування Уявіть: користувач вводить «Тверск», система за 300 мс пропонує 5 варіантів. Без правильної реалізації кожне натискання — окремий запит до API, 70% користувачів кидають форму при затримках понад 2 секунди. Середній час введення адреси з авт

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Оптимізація введення адреси: автодоповнення у мобільних застосунках
Середній
від 1 дня до 3 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Оптимізація введення адреси: автодоповнення та кешування

Уявіть: користувач вводить «Тверск», система за 300 мс пропонує 5 варіантів. Без правильної реалізації кожне натискання — окремий запит до API, 70% користувачів кидають форму при затримках понад 2 секунди. Середній час введення адреси з автодоповненням — 8 секунд, без нього — 35 секунд (за даними Nielsen Norman Group). Технічна складність — не просто прикрутити бібліотеку, а обрати провайдера, налаштувати дебаунс, кеш та session token. Розберемо, як це зробити правильно.

Як обрати провайдера для геокодування?

Провайдер Сильні сторони Слабкі сторони
Google Places Autocomplete API Найкраще покриття глобально, POI, бізнеси Дорогий при високому трафіку, слабше по корпусах в Україні
DaData Найкращий по адресах України (ФІАС/КЛАДР), точність >95% Тільки Україна
Nominatim (OpenStreetMap) Безкоштовно, глобально Немає SLA, повільніше, гірше за якістю на 30% vs DaData
HERE Geocoding Добре в Європі, є офлайн-пакети Дорожчий за Google для малих обсягів
Yandex Geocoder Добре по СНД Вимагає акаунт, обмеження за умовами

Для більшості українських проєктів ми рекомендуємо зв'язку DaData + Google: DaData як перший пріоритет, Google як fallback для закордонних адрес. Це знижує вартість запитів на 40% відносно використання лише Google. DaData в 2 рази точніший за Nominatim для адрес України — це критично для логістики. Google Places з session token в 3–5 разів дешевший, ніж без токена.

Чому важливий session token у Google Places?

На iOS використовуємо GooglePlaces pod та GMSPlacesClient.findAutocompletePredictions(fromQuery:filter:sessionToken:callback:). Ключовий момент — GMSAutocompleteSessionToken: один токен на всю сесію пошуку (від першого символу до вибору результату). Це знижує вартість у 3–5 разів порівняно із запитом без токена. Як зазначає Google Places documentation: «Використання сесійних токенів дозволяє згрупувати кілька запитів в один білінг».

let token = GMSAutocompleteSessionToken() let filter = GMSAutocompleteFilter() filter.type = .address filter.countries = ["UA", "BY", "KZ"] placesClient.findAutocompletePredictions( fromQuery: query, filter: filter, sessionToken: token ) { results, error in guard let results else { return } self.suggestions = results.map { $0.attributedFullText.string } } 

Після вибору адреси викликаємо fetchPlace(fromPlaceID:placeFields:sessionToken:) для отримання координат — і обнуляємо токен. Без fetchPlace координати не отримати через автодоповнення.

На Android — Places.initialize(context, apiKey) + PlacesClient. У Jetpack Compose:

val placesClient = Places.createClient(context) val request = FindAutocompletePredictionsRequest.builder() .setQuery(query) .setSessionToken(AutocompleteSessionToken.newInstance()) .setTypesFilter(listOf(PlaceTypes.ADDRESS)) .setCountries("UA", "BY") .build() placesClient.findAutocompletePredictions(request) .addOnSuccessListener { response -> _suggestions.value = response.autocompletePredictions } 

Що дає дебаунс запитів?

Без дебаунса кожне натискання клавіші — окремий API-запит. При середньому введенні 4 символи на секунду це 4 запити замість одного. Наш досвід показує, що правильний дебаунс 350 мс скорочує кількість запитів на 70%.

Покрокова реалізація дебаунса:

  1. Створіть Publisher/Flow з текстового поля.
  2. Застосуйте оператор debounce(for: 350 ms).
  3. Додайте фільтр довжини запиту >= 3 символи.
  4. Використовуйте flatMapLatest для відміни попереднього запиту.

На iOS через Combine:

searchTextField.textPublisher .debounce(for: .milliseconds(350), scheduler: DispatchQueue.main) .removeDuplicates() .sink { [weak self] query in guard query.count >= 3 else { return } self?.fetchSuggestions(for: query) } 

На Android через StateFlow:

searchQuery .debounce(350) .filter { it.length >= 3 } .distinctUntilChanged() .flatMapLatest { fetchSuggestions(it) } .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) 

flatMapLatest відміняє попередній запит при новому введенні — без цього старі результати можуть перекрити актуальні.

Офлайн і кеш: як покращити UX?

Останні 10–20 обраних адрес зберігаємо локально (UserDefaults / SharedPreferences) і показуємо при порожньому полі введення. Це вирішує найчастіший кейс: користувач кожного разу замовляє додому.

Для історії пошуку — Room / Core Data з колонками address_string, lat, lon, last_used_at. При введенні спочатку шукаємо по локальній базі (LIKE-запит), потім паралельно запитуємо API — показуємо спочатку локальний результат, замінюємо на API-результат при приході. Час відгуку з кешу — 2–5 мс проти 200–500 мс з API.

Приклад повного рішення для iOS (SwiftUI + Combine)
class AddressSearchViewModel: ObservableObject { @Published var query = "" @Published var suggestions: [String] = [] private var cancellables = Set<AnyCancellable>() private let placesClient = GMSPlacesClient() private let token = GMSAutocompleteSessionToken() init() { $query .debounce(for: .milliseconds(350), scheduler: DispatchQueue.main) .removeDuplicates() .filter { $0.count >= 3 } .flatMapLatest { [weak self] query -> AnyPublisher<[String], Never> in guard let self = self else { return Just([]).eraseToAnyPublisher() } return Future { promise in let filter = GMSAutocompleteFilter() filter.type = .address filter.countries = ["UA"] self.placesClient.findAutocompletePredictions( fromQuery: query, filter: filter, sessionToken: self.token ) { results, error in guard let results = results, error == nil else { promise(.success([])) return } promise(.success(results.map { $0.attributedFullText.string })) } }.eraseToAnyPublisher() } .receive(on: DispatchQueue.main) .assign(to: &$suggestions) } func selectAddress(_ placeID: String) { let token = GMSAutocompleteSessionToken() let fields: GMSPlaceField = [.coordinate, .formattedAddress] placesClient.fetchPlace(fromPlaceID: placeID, placeFields: fields, sessionToken: token) { place, error in guard let coordinate = place?.coordinate else { return } // зберігаємо координати } } } 

Як тестувати автокомпліт на граничних випадках?

Тестування автокомпліту виявляє помилки, які складно відловити в production. Ми використовуємо підхід mock-шар: підміняємо API-відповіді тестовими даними (порожня відповідь, затримки, помилки). Перевіряємо граничні рядки: порожній рядок, один символ, спецсимволи (!@#$), дуже довгі адреси (200+ символів), адреси з нестандартними літерами (умлаути, кирилиця). Також імітуємо збої мережі та тайм-аути — застосунок має коректно показувати fallback-повідомлення та не крашитися. У нас є чек-лист із 25+ сценаріїв для кожного проєкту.

Що входить у роботу?

  • Вибір та інтеграція провайдера (DaData, Google, Yandex).
  • Розробка UI-компонента з випадним списком (SwiftUI / Jetpack Compose).
  • Реалізація дебаунса, відміни запитів, session token.
  • Локальне кешування історії адрес.
  • Обробка помилок: відсутність мережі, ліміти API, некоректне введення.
  • Тестування на граничних рядках (порожнє введення, спецсимволи, дуже довгі адреси).
  • Документація з інтеграції.

Ми реалізували пошук адрес у 30+ проєктах — від служб доставки до геоінформаційних систем. Гарантуємо стабільну роботу при високих навантаженнях. Оцініть свій проєкт — зв'яжіться з нами для консультації.

Термін реалізації: два–чотири дні — провайдер, UI, дебаунс, кеш історії, тестування. Вартість розраховується індивідуально під ваші завдання. Отримайте консультацію — дізнайтеся, скільки займе інтеграція вашого застосунку.