Реалізація міграції кешу при оновленні мобільного додатку
Уявіть: ви випустили оновлення, а користувачі масово скаржаться на вильоти та старі дані. Причина — неінвалідований кеш. Старі зображення завантажені під старими ключами, JSON-відповіді серіалізовані в застарілий формат, HTTP-кеш містить заголовки з битими URL. Якщо не очистити кеш при оновленні — користувач бачить перемішані дані з різних версій, або додаток падає на десеріалізації. Розглянемо на прикладі реального проекту: додаток для доставки, де після оновлення користувачі бачили ціни зі старої відповіді API, що призводило до збитків. Правильна інвалідація кешу вирішила проблему за один день. Міграція кешу — обов'язковий етап будь-якого оновлення. Ми, розробники з 10-річним досвідом, зібрали перевірені методи для iOS та Android.
Чому кеш стає невалідним після оновлення?
Причина — несумісність форматів даних між версіями. Припустимо, у версії 1.0 API повертав об'єкт { "name": "foo" }, а в 2.0 — { "full_name": "foo bar" }. Якщо додаток закешував старий JSON і намагається десеріалізувати його в нову модель — крах. Аналогічно із зображеннями: змінилися шляхи, розміри або хеші. Згідно з документацією Apple URLCache, HTTP-кеш також може містити застарілі заголовки, що призводить до помилок завантаження.
Версіонування ключів кешу
Найпростіший і найнадійніший підхід: прив'язати ключі кешу до версії додатку або до версії API.
// Android — простір імен кешу за версією object CacheKeyBuilder { private val appVersion = BuildConfig.VERSION_CODE fun forImage(imageId: String) = "img_v${appVersion}_$imageId" fun forApiResponse(endpoint: String) = "api_v${appVersion}_$endpoint" } // iOS — ключ з номером білда struct CacheKeyBuilder { static let appVersion = Bundle.main.buildVersionNumber static func imageKey(_ id: String) -> String { "img_v\(appVersion)_\(id)" } static func apiKey(_ endpoint: String) -> String { "api_v\(appVersion)_\(endpoint)" } } При оновленні VERSION_CODE або buildVersionNumber всі ключі змінюються — старий кеш перестає використовуватися. Але при цьому старі файли залишаються на диску і потрібне явне очищення.
Очищення застарілого кешу при старті
// iOS class CacheManager { private let defaults = UserDefaults.standard private let lastVersionKey = "lastCachedVersion" func cleanupIfNeeded() { let current = Bundle.main.buildVersionNumber let last = defaults.string(forKey: lastVersionKey) ?? "" guard current != last else { return } clearDiskCache() clearURLCache() defaults.set(current, forKey: lastVersionKey) } private func clearDiskCache() { let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! try? FileManager.default.removeItem(at: cacheDir.appendingPathComponent("ImageCache")) } private func clearURLCache() { URLCache.shared.removeAllCachedResponses() } } Викликаємо в application(_:didFinishLaunchingWithOptions:) до ініціалізації UI.
// Android — очищення при старті class CacheCleaner(private val context: Context) { fun cleanIfNeeded() { val prefs = context.getSharedPreferences("cache", Context.MODE_PRIVATE) val lastVersion = prefs.getInt("lastVersion", 0) val currentVersion = BuildConfig.VERSION_CODE if (lastVersion == currentVersion) return Glide.get(context).clearDiskCache() val cacheDir = File(context.cacheDir, "http-cache") cacheDir.deleteRecursively() prefs.edit().putInt("lastVersion", currentVersion).apply() } } Виклик з Application.onCreate() у фоновому потоці.
Kingfisher (iOS) та Glide (Android)
Обидві бібліотеки використовують власні дискові кеші. Kingfisher зберігає кеш у Library/Caches/com.onevcat.Kingfisher.ImageCache. Очищення:
KingfisherManager.shared.cache.clearDiskCache() KingfisherManager.shared.cache.clearMemoryCache() Glide: Glide.get(context).clearDiskCache() — тільки з фонового потоку. Офіційні репозиторії: Kingfisher, Glide.
Порівняння підходів
| Підхід | Складність | Час виконання | Ризик втрати даних |
|---|---|---|---|
| Повне очищення кешу | Низька | 0.5 дня | Високий (всі тимчасові дані зникають) |
| Версіонування ключів + фонове очищення старих | Середня | 1 день | Низький (важливий кеш зберігається до застарівання) |
| Інкрементальна міграція | Висока | 2-3 дні | Дуже низький (тільки несумісні записи) |
Як обрати стратегію міграції кешу?
Для невеликих проектів достатньо повного очищення при кожному оновленні — це швидко реалізувати і легко перевірити. Якщо важливі швидкість запуску та користувацький досвід, обирайте версіонування ключів з фоновим очищенням. Для фінансових або медичних додатків, де кожен запис критичний, використовуйте інкрементальну міграцію з точковою інвалідацією.
Що входить в роботу
| Етап | Результат |
|---|---|
| Аудит кешування | Опис усіх точок кешування, поточні ризики |
| Проектування стратегії | Вибір підходу під вашу архітектуру |
| Реалізація модулів | Native-код для iOS та Android з Unit-тестами |
| Інтеграція та тестування | Перевірка на кількох версіях додатку |
| Документація | Інструкція з підтримки та деплою |
| Навчання команди | Розбір коду та best practices |
Процес роботи
- Аудит кешування — 0.5 дня.
- Проектування стратегії — 0.5 дня.
- Реалізація на iOS та Android — 1-2 дні.
- Тестування на реальних оновленнях — 0.5 дня.
- Деплой та моніторинг — 0.5 дня.
Терміни
Базова інвалідація кешу при оновленні: від 0,5 дня. З версіонованими ключами, збереженням важливого кешу та фоновим очищенням: від 1 дня. Для складних проектів з кількома джерелами кешу: від 2 до 3 днів.
Чек-лист міграції кешу
Чек-лист міграції кешу
- [ ] Версіонування ключів для зображень та API
- [ ] Код очищення кешу при старті (залежно від версії)
- [ ] Очищення HTTP-кешу (URLCache / HttpCache)
- [ ] Фонове очищення старих файлів (не блокує запуск)
- [ ] Тест: оновлення з версії N-1 до N та перевірка даних
- [ ] Моніторинг крашів після оновлення (Crashlytics)
Версіонування ключів надійніше за повне очищення кешу — воно не вимагає видалення всіх файлів, що економить час старту. Однак старі файли все одно необхідно видаляти при старті, щоб не заповнити сховище.
Наші інженери мають 10+ років досвіду в мобільній розробці та гарантують коректну міграцію кешу без втрати даних. Зв'яжіться з нами для аудиту поточної системи кешування. Отримайте консультацію з вирішення проблем з кешем. Економія часу на розробку — до 2 днів, а зниження витрат на підтримку покриває вартість реалізації протягом місяця.







