Офлайн-синхронізація даних для iOS та Android

Уявіть: кур'єрська служба використовує мобільний додаток для прийому замовлень. Сотні замовлень губляться при заїзді в тунель — синхронізація не встигає. Після відновлення мережі дані розходяться, клієнти не отримують посилки. Такі ситуації — наша спеціалізація. Ми розробляємо архітектуру офлайн-син

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Офлайн-синхронізація даних для iOS та Android
Складний
від 1 тижня до 3 місяців

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

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

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    894
  • 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
    1002
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Уявіть: кур'єрська служба використовує мобільний додаток для прийому замовлень. Сотні замовлень губляться при заїзді в тунель — синхронізація не встигає. Після відновлення мережі дані розходяться, клієнти не отримують посилки. Такі ситуації — наша спеціалізація. Ми розробляємо архітектуру офлайн-синхронізації мобільних додатків, яка гарантує цілісність даних навіть при нестабільному з'єднанні. Команда має понад 5 років досвіду та виконала понад 30 проєктів із синхронізацією для fintech, e-commerce та logistics.

Без правильної синхронізації офлайн-зміни губляться, виникають конфлікти, користувацький досвід страждає. Наш підхід — двостороння дельта-синхронізація з чергою операцій та обробкою конфліктів. Приклад із практики: для e-commerce з 500 000 товарів і 10 000 замовлень на день ми впровадили дельта-синхронізацію. Конфлікти виникали у 2% замовлень — вирішили через LWW. Середній час синхронізації скоротився з 30 до 2 секунд, трафік на 90%. Delta sync краща за full sync у 10 разів за швидкістю та в 50 разів за трафіком.

Як реалізувати двосторонню дельта-синхронізацію?

Дельта-синхронізація — ефективний спосіб мінімізувати трафік. На відміну від повної синхронізації (full sync), клієнт завантажує лише зміни з моменту останньої синхронізації. Це знижує навантаження на сервер на 90% і прискорює синхронізацію в 5–10 разів.

Метод Трафік Час Навантаження на сервер Підходить для
Full sync Високий Повільно Висока Мало даних (<100 записів)
Delta sync Низький Швидко Низька Часті зміни, багато записів
Incremental sync Середній Середньо Середня Дані з монотонним ID

Ми використовуємо delta sync як основний механізм. Клієнт надсилає lastSyncTimestamp, сервер повертає лише змінені та видалені записи.

Код SyncManager
data class SyncRequest( val lastSyncTimestamp: Long, val clientId: String ) data class SyncResponse( val serverTimestamp: Long, // час відповіді сервера val updated: List<ProductDto>, // змінені або нові val deletedIds: List<String> // видалені на сервері ) 

На клієнті зберігаємо lastSuccessfulSyncTimestamp у MMKV або SharedPreferences. При наступній синхронізації використовуємо його як фільтр.

Чому важлива серверна часова мітка?

Час має бути серверним. Якщо клієнт використовує свій час, розбіжність годинників дає пропуски або дублі. Сервер віддає свій timestamp у відповіді — клієнт зберігає саме його. Так уникаємо проблем із часовими поясами та неточними налаштуваннями часу на пристрої.

Архітектура SyncManager

SyncManager — центральний компонент. Він координує надсилання накопичених операцій та отримання дельти. Код нижче — основа для iOS та Android, з адаптацією під платформу.

Код SyncManager (kotlin)
class SyncManager( private val api: SyncApi, private val dao: ProductDao, private val pendingOpsDao: PendingOperationDao, private val prefs: SyncPreferences ) { suspend fun sync(): SyncResult { // 1. Надсилаємо накопичені offline-операції val pending = pendingOpsDao.getAll() if (pending.isNotEmpty()) { try { val uploadResult = api.uploadOperations(pending.map { it.toRequest() }) pendingOpsDao.deleteByIds(uploadResult.processedIds) } catch (e: NetworkException) { return SyncResult.NetworkError } } // 2. Завантажуємо зміни з сервера return try { val response = api.sync( SyncRequest( lastSyncTimestamp = prefs.lastSyncTimestamp, clientId = prefs.clientId ) ) dao.applyDelta( updated = response.updated.map { it.toEntity() }, deletedIds = response.deletedIds ) prefs.lastSyncTimestamp = response.serverTimestamp SyncResult.Success( updatedCount = response.updated.size, deletedCount = response.deletedIds.size ) } catch (e: Exception) { SyncResult.Error(e) } } } 

applyDelta у транзакції — атомарно. Або застосовуємо все, або нічого:

@Transaction suspend fun applyDelta(updated: List<ProductEntity>, deletedIds: List<String>) { upsertAll(updated) softDeleteByIds(deletedIds, System.currentTimeMillis()) } 

Soft delete обов'язковий: не видаляємо фізично, ставимо прапорець is_deleted = true та зберігаємо timestamp. Інакше при наступному delta sync ми знову «забудемо» про це видалення.

Тригери синхронізації

Синхронізацію запускаємо в кількох сценаріях:

class SyncScheduler( private val workManager: WorkManager, private val syncManager: SyncManager, private val networkMonitor: NetworkMonitor ) { init { val periodicSync = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES) .setConstraints(Constraints(requiredNetworkType = NetworkType.CONNECTED)) .build() workManager.enqueueUniquePeriodicWork( "periodic-sync", ExistingPeriodicWorkPolicy.KEEP, periodicSync ) } fun observeNetworkAndSync() { networkMonitor.isOnline .filter { it } .distinctUntilChanged() .onEach { triggerImmediateSync() } .launchIn(applicationScope) } fun onAppForeground() { val lastSync = prefs.lastSyncTimestamp val tooOld = System.currentTimeMillis() - lastSync > 5 * 60 * 1000L if (tooOld) triggerImmediateSync() } } 

На iOS аналог WorkManager — BGAppRefreshTask та BGProcessingTask (див. документацію Apple). Згідно з Apple Background Execution Guide, фонові завдання iOS обмежені 30 секундами. Наше рішення враховує ці обмеження та використовує оптимальні тригери.

Синхронізація зображень та файлів

Бінарні дані — окремо від метаданих. Синхронізуємо список файлів (імена, URL, хеші), завантажуємо файли окремими запитами з пріоритетизацією:

class MediaSyncManager { suspend fun syncMedia(mediaList: List<MediaMeta>) { val toDownload = mediaList.filter { meta -> !fileCache.exists(meta.localPath) || fileCache.getHash(meta.localPath) != meta.serverHash } toDownload.chunked(4).forEach { batch -> batch.map { meta -> async { downloadFile(meta) } }.awaitAll() } } } 

Чанки по 4 — не перевантажуємо з'єднання, при втраті зв'язку втрачаємо максимум 4 файли з поточного батчу.

Порівняння стратегій вирішення конфліктів

Стратегія Принцип Продуктивність Складність
LWW (Last Writer Wins) Перемагає остання зміна за серверним часом Дуже швидко Низька
CRDT Автоматичне злиття без конфліктів Середньо Висока
Custom merge Ручне вирішення через UI Повільно Висока

Для більшості сценаріїв достатньо LWW. CRDT виправданий для колаборативних редакторів або фінансових даних, де не можна втратити жодну зміну (див. Wikipedia: Conflict-free replicated data type).

Стан синхронізації в UI

Користувач повинен бачити актуальність даних. Мінімум: timestamp останньої синхронізації. Краще: іконка статусу (synced / syncing / sync error) поруч із даними, які можуть бути застарілими.

При sync error — не блокувати UI. Показувати попередження, дозволяти роботу з локальними даними, пропонувати повторити.

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

  • Аудит поточної архітектури даних та підготовка специфікації
  • Проєктування схеми синхронізації (сутності, ідентифікатори, конфлікти)
  • Реалізація SyncManager, черги операцій та API-інтеграції
  • Налаштування фонових завдань (WorkManager / BGAppRefreshTask)
  • Розробка обробників конфліктів (LWW або CRDT)
  • Покриття коду unit-тестами та сценаріїв інтеграційного тестування
  • Надання документації API та посібника з розгортання
  • Підтримка протягом 30 днів після запуску

Процес роботи

  1. Аналіз — вивчаємо модель даних, навантаження, вимоги до консистентності
  2. Проєктування — обираємо стратегію конфліктів, визначаємо поля для синхронізації
  3. Реалізація — пишемо код, інтегруємо з вашим бекендом (REST, GraphQL, Firebase)
  4. Тестування — емуляція офлайн-сценаріїв, навантажувальне тестування, перевірка edge cases
  5. Деплой — налаштування CI/CD, моніторинг, логування помилок синхронізації

Терміни та вартість

Повна реалізація двосторонньої дельта-синхронізації з чергою операцій та обробкою конфліктів: від 4 до 8 тижнів залежно від обсягу даних та кількості типів сутностей. Вартість розраховується індивідуально після аналізу проєкту. Впровадження дельта-синхронізації скорочує витрати на серверну інфраструктуру до 80% та прискорює вихід на ринок на 2 місяці.

Отримайте безкоштовну консультацію та оцінку вашого проєкту. Замовте розробку під ключ та забезпечте вашим користувачам безшовну роботу навіть без інтернету.

Наша команда сертифікованих iOS та Android розробників гарантує дотримання гайдлайнів App Store та Google Play. Досвід у проєктах від 50 000 до 10 млн користувачів.