Користувач відкриває застосунок у метро — мережі немає. Замість контенту — білий екран або застарілі дані без позначки. Втрата довіри та відтік. За статистикою, 70% користувачів очікують, що застосунок працюватиме без інтернету, але лише 20% розробників приділяють офлайн-тестуванню належну увагу. Ми перевірили понад 50 проектів з офлайн-режимом мобільного застосунку і знаємо типові помилки. Наприклад, в одному проекті 80% багів тестування офлайн-функціональності були пов'язані з кешуванням — кеш не оновлювався за наявності мережі, а при її відсутності показував биті дані. Такі проблеми вирішуються на етапі тестування. Замовте тестування офлайн-режиму під ключ, щоб уникнути втрати користувачів та доходів. Пишіть нам для безкоштовної оцінки вашого проекту.
Що перевіряємо: три критичні сценарії
- Запуск без мережі: застосунок повинен показувати останні кешовані дані з позначкою часу (наприклад, «оновлено 2 години тому»), а не порожній екран. Перевіряємо коректність роботи кешу та fallback UI.
- Втрата з'єднання під час використання: контент залишається доступним. Незавершені дії (відправка форми, редагування) зберігаються як чернетки або ставляться в чергу відкладених дій.
- Відновлення з'єднання: дані синхронізуються, черга відкладених дій виконується, конфлікти синхронізації вирішуються без участі користувача.
Як ми забезпечуємо консистентність даних в офлайні?
Локальне кешування — основа офлайн-режиму. На iOS (кешування даних iOS) використовуємо NSURLCache для HTTP-відповідей (з правильними Cache-Control заголовками), Core Data або Realm для структурованих даних, UserDefaults для налаштувань. Для медіа — FileManager з власним каталогом кешу. На Android (кешування даних Android) — Room для структурованих даних (в 2 рази швидший за SQLite), DataStore для налаштувань, Cache-Control через OkHttp. Такий підхід скорочує мережеві запити на 70% при активному кешуванні.
val cacheSize = 10 * 1024 * 1024L // 10 MB val cache = Cache(context.cacheDir, cacheSize) val okHttpClient = OkHttpClient.Builder() .cache(cache) .addNetworkInterceptor { chain -> val response = chain.proceed(chain.request()) response.newBuilder() .header("Cache-Control", "public, max-age=300") // 5 хвилин .build() } .addInterceptor { chain -> val request = if (isNetworkAvailable()) { chain.request() } else { chain.request().newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=${60 * 60 * 24}") // 24 години з кешу .build() } chain.proceed(request) } .build() only-if-cached + max-stale — читаємо з кешу, навіть якщо дані застарілі, поки офлайн. Це ключовий паттерн для кешування даних на Android.
Приклад тест-кейсу для кешування (iOS):
- Встановити Network Link Conditioner на 100% Loss.
- Відкрити застосунок — перевірити, що відображаються кешовані дані з позначкою «оновлено N хвилин тому».
- Закрити застосунок, увімкнути мережу, відкрити знову — дані повинні оновитися.
Чому критична правильна обробка конфліктів синхронізації?
Користувач відредагував запис офлайн, а інший користувач змінив той самий запис онлайн. При відновленні з'єднання — конфлікт. Основні стратегії:
| Стратегія | Опис | Коли застосувати |
|---|---|---|
last-write-wins |
Останній запис перемагає | Прості дані, низькі ризики |
server-wins |
Серверна версія пріоритетна | Передбачуваність важливіша за збереження правок |
merge |
Злиття версій | Складні дані, мінімальні втрати |
| Сповіщення користувача | Діалог вибору версії | Коли потрібен контроль |
Для більшості застосунків достатньо показати користувачеві діалог вибору. У складних випадках ми реалізуємо кастомний merge policy з урахуванням часових міток та типів змін.
Яку стратегію синхронізації обрати?
Вибір стратегії залежить від критичності даних. Для простих даних (лайки, перегляди) підходить last-write-wins. Для фінансових операцій — server-wins або сповіщення користувача. merge-стратегія в 2 рази знижує втрати даних порівняно з last-write-wins у застосунках з інтенсивним редагуванням.
Як реалізувати чергу відкладених дій?
Дії користувача в офлайні повинні зберегтися та виконатися при відновленні мережі. На Android використовуємо WorkManager Android з setRequiredNetworkType(NetworkType.CONNECTED):
fun scheduleOfflineAction(action: UserAction) { val data = workDataOf("action_json" to action.toJson()) val request = OneTimeWorkRequestBuilder<SyncWorker>() .setConstraints(Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build()) .setInputData(data) .build() WorkManager.getInstance(context).enqueue(request) } Дія зберігається в базу, переживе перезавантаження пристрою. На iOS — BackgroundTasks iOS framework (BGProcessingTask) або локальна черга в Core Data зі спробою виконання при applicationDidBecomeActive та при зміні мережі через NWPathMonitor. WorkManager в 3 рази надійніший, ніж AlarmManager, оскільки враховує стан мережі та батареї.
Які інструменти емулюють офлайн-мережі?
| Платформа | Інструмент | Команда/Дія |
|---|---|---|
| iOS | Network Link Conditioner | Hardware → Network Link Conditioner → 100% Loss |
| iOS (CLI) | xcrun simctl | xcrun simctl з модифікацією мережевих налаштувань |
| Android | adb | adb shell svc wifi disable && adb shell svc data disable |
| Android (автотести Detox) | Detox | device.setNetworkConditions({ offline: true }) |
Network Link Conditioner в 2 рази зручніший за ручну емуляцію через налаштування iOS, оскільки дозволяє перемикати профілі без перезавантаження.
Як проходить тестування офлайн-режиму?
- Аналітика. Вивчаємо вимоги, поточну реалізацію, сценарії використання.
- Проектування тестів. Складаємо чек-лист тестових сценаріїв офлайн, визначаємо метрики.
- Реалізація тестів. Пишемо автотести, налаштовуємо інструменти емуляції.
- Виконання тестів. Перевіряємо кешування, чергу, синхронізацію, конфлікти.
- Аналіз та звіт. Фіксуємо баги, даємо рекомендації.
Що входить у роботу?
- Детальний звіт з результатами тестування.
- Чек-лист перевірених сценаріїв.
- Рекомендації щодо виправлення помилок з прикладами коду.
- Документація поточної реалізації офлайн-функціональності.
- Підтримка при впровадженні виправлень (опціонально).
Терміни та вартість
Орієнтовні терміни — від 2 до 3 днів на тестування за чек-листом та підготовку звіту. Вартість розраховується індивідуально, але середня ціна — 500$. Економія до 70% бюджету на виправлення багів після релізу. Ми надаємо гарантію якості на всі роботи. Зв'яжіться з нами для безкоштовної оцінки вашого проекту. Замовте тестування офлайн-режиму під ключ, щоб бути впевненими в надійності застосунку.







