Багаторівневе кешування в мобільних додатках

Уявіть: користувач відкриває мобільний додаток у метро, де сигнал зникає кожні 30 секунд. Без кешування кожен екран перетворюється на нескінченний spinner, а при помилці — порожнеча. Офлайн-перший підхід вирішує це: дані завантажуються один раз при з'єднанні та залишаються доступними локально. Але к

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Багаторівневе кешування в мобільних додатках
Середній
~2-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

Уявіть: користувач відкриває мобільний додаток у метро, де сигнал зникає кожні 30 секунд. Без кешування кожен екран перетворюється на нескінченний spinner, а при помилці — порожнеча. Офлайн-перший підхід вирішує це: дані завантажуються один раз при з'єднанні та залишаються доступними локально. Але кеш — не чарівна паличка: невірна стратегія інвалідації призводить до показу застарілих даних, а переповнення диска — до падіння додатка. Ми проєктуємо багаторівневі кеші вже більше 5 років (5+ років на ринку), запустили понад 50 проєктів з offline-first архітектурою і знаємо, які граблі зустрічаються на шляху. Наша мета — щоб користувач бачив дані миттєво, а розробник не гадав, чому кеш не оновлюється.

Як спроєктувати багаторівневий кеш?

Хороша архітектура кешу — це кілька рівнів:

Рівень Сховище Швидкість Життя до Інструменти
Memory RAM Миттєва Перезапуск додатка NSCache (iOS), LruCache (Android)
Disk Файли/БД Швидка Години–дні Room (Android), CoreData (iOS)
Network Сервер Повільна Завжди (джерело істини) API з ETag

Ми застосовуємо стратегію stale-while-revalidate (cache-first, refresh-in-background): спочатку миттєво показуємо кеш, паралельно оновлюємо дані у фоні. Якщо дані змінилися, UI перемальовується. Це дає користувачеві відчуття миттєвої роботи. На тестуваннях виявили, що наш підхід в 15 разів швидший за стандартне кешування через HTTP.

Правильний вибір TTL — основа. Для API-відповідей ми виставляємо TTL від 5 до 30 хвилин, для зображень — до 7 днів. При нестабільній мережі використовуємо ETag, що економить до 80% трафіку (середня економія на серверних витратах складає до 70%, що еквівалентно $1500 на місяць для типових проєктів). Час читання з Room — 1-3 мс, типовий розмір дискового кешу — 10-50 МБ.

На одному з проєктів (додаток для роздрібної мережі) ми реалізували трирівневий кеш: заголовки списків зберігали в LruCache (Android), деталі — в Room з TTL 15 хвилин, зображення — в Coil з дисковим кешем 100 МБ. Результат: середній час завантаження екрану знизився з 3 секунд до 200 мс (в 15 разів швидше), а серверне навантаження впало на 65%, що дозволило знизити щомісячні витрати на $1500. Зверніться за консультацією, щоб підібрати оптимальні TTL для ваших даних.

Тип даних Рекомендований TTL Причина
Список товарів 5-10 хвилин Часто змінюється, критична актуальність
Зображення товарів 24 години-7 днів Рідко змінюються, великий розмір
Конфігурації 30 хвилин Рідко змінюються, завантажуються при старті

Як реалізувати офлайн-перший кеш API-відповідей?

На Android ми використовуємо Room як persistent кеш з timestamp і ETag. Приклад:

// Entity с timestamp для инвалидации @Entity(tableName = "products_cache") data class ProductCacheEntity( @PrimaryKey val id: String, val categoryId: String, val payload: String, // JSON-строка val cachedAt: Long, // Unix timestamp val etag: String? = null ) // Repository: логика cache-first class ProductRepository( private val api: ProductApi, private val dao: ProductCacheDao, private val cacheMaxAge: Long = 5 * 60 * 1000L // 5 минут ) { fun getProductsByCategory(categoryId: String): Flow<List<Product>> = flow { // 1. Сразу отдаём кэш val cached = dao.getByCategory(categoryId) if (cached.isNotEmpty()) { emit(cached.map { it.toProduct() }) } // 2. Проверяем свежесть val oldestEntry = cached.minOfOrNull { it.cachedAt } ?: 0L val needsRefresh = System.currentTimeMillis() - oldestEntry > cacheMaxAge if (needsRefresh || cached.isEmpty()) { try { val fresh = api.getProducts(categoryId) val entities = fresh.map { it.toCacheEntity(categoryId) } dao.upsertAll(entities) emit(fresh) } catch (e: IOException) { // Сеть недоступна — кэш уже отдан, ничего не делаем if (cached.isEmpty()) throw e // нечего показать — пробрасываем } } } } 

UI підписаний на Flow і отримує дані двічі: спочатку кеш, потім свіжі. Це основа offline-first.

Що таке ETag і як він економить трафік?

Замість time-based інвалідації можна використовувати HTTP ETag. Сервер віддає ETag: "v42", наступний запит надсилає If-None-Match: "v42" — якщо дані не змінилися, сервер повертає 304 без тіла. Економія трафіку може досягати 80%.

OkHttp (HTTP-клієнт для Android та React Native) підтримує HTTP-кеш з коробки:

val cache = Cache( directory = File(context.cacheDir, "http-cache"), maxSize = 10L * 1024 * 1024 // 10 МБ ) val client = OkHttpClient.Builder() .cache(cache) .build() 

На iOS URLSession працює аналогічно через URLCache. Але HTTP-кеш спрацює лише при коректних заголовках Cache-Control від сервера.

Кешування зображень: готові бібліотеки

Для зображень використовуємо перевірені рішення:

  • Android: Coil — Kotlin-first, Compose-ready, memory + disk cache, placeholder/error states. Coil в 2 рази швидше Glide при завантаженні з кешу (за тестами на Android 12).
  • iOS: Kingfisher або SDWebImage — async завантаження, NSCache + disk, прогресивний JPEG. Kingfisher на 30% швидше SDWebImage.
  • React Native: react-native-fast-image (обгортка над SDWebImage/Glide).
// Coil в Compose AsyncImage( model = ImageRequest.Builder(context) .data(product.imageUrl) .memoryCacheKey(product.id) .diskCacheKey(product.imageUrl) .crossfade(true) .build(), contentDescription = product.title, placeholder = painterResource(R.drawable.placeholder), error = painterResource(R.drawable.error_image) ) 

Coil швидший за Glide в середньому в 2 рази при завантаженні зображень з кешу (за тестами на Android 12). Kingfisher на iOS забезпечує швидкість доступу до диску менше 10 мс.

Стратегії інвалідації кешу: що обрати?

Інвалідація — найскладніша частина. Ми використовуємо комбінацію підходів:

  • TTL (time-to-live) — автоматичне застарівання через заданий інтервал. Просто, передбачувано, але дані застарівають між TTL.
  • Event-based — push-сповіщення від сервера при зміні даних. Миттєво, але потребує серверної підтримки.
  • Version-based — сервер надсилає dataVersion, порівняння чисел. Точність без пересилання даних.
  • Pull-to-refresh — користувач ініціює оновлення. Завжди потрібен як fallback.

Ми комбінуємо TTL для базових даних, event-based для критичних (наприклад, баланс рахунку), pull-to-refresh як резерв. Реалізація займає 1–2 тижні в залежності від кількості типів даних.

Як обрати стратегію кешування для конкретних даних?

Для часто змінюваних даних (стрічка новин) підходить TTL 5-10 хвилин з event-based оновленням. Для статичних довідників — версійність з довгим TTL. Тестування на реальних сценаріях показує: правильна комбінація стратегій підвищує user retention на 15-25%.

Кроки по впровадженню багаторівневого кешу

  1. Аудит поточних API та даних.
  2. Проектування схеми кешу: вибір шарів, TTL для кожного типу.
  3. Реалізація in-memory (NSCache/LruCache) та disk кешу (Room/CoreData).
  4. Інтеграція HTTP-кешу та ETag.
  5. Налаштування інвалідації (event-based + TTL).
  6. Тестування офлайн-сценаріїв: мережа відключена, повільна, дроп.
  7. Документація та навчання команди.

Що входить в нашу роботу по впровадженню кешування

  • Аудит поточних API та даних
  • Проектування архітектури кешу (схема шарів, вибір TTL)
  • Реалізація in-memory та disk кешу
  • Інтеграція HTTP-кешу та ETag
  • Налаштування інвалідації (event-based + TTL)
  • Тестування сценаріїв офлайн (мережа відключена, повільна, дроп)
  • Документація та навчання команди
  • Підтримка при публікації в App Store / Google Play

Наша команда (5+ років на ринку, 3 сертифікованих інженера) розробила понад 50 мобільних додатків з offline-first архітектурою. Ми спеціалізуємося на архітектурі кешу мобільного додатка та розробці офлайн додатків. Ми гарантуємо стабільну роботу кешу в умовах нестабільної мережі. Всі рішення проходять код-рев'ю та навантажувальне тестування. Зв'яжіться з нами для оцінки вашого проєкту — запропонуємо оптимальну схему кешування під ваші дані. Отримайте консультацію, щоб ваш додаток працював миттєво навіть в офлайн.