Оптимізація часу запуску мобільного застосунку (Warm Start)
У нашій практиці ми нерідко бачимо, як застосунок, який чудово працює при холодному старті, гальмує при поверненні з фону — на mid-range Android-пристроях затримка сягає 2–3 секунд. Warm start виникає, коли процес застосунку живий, але Activity/ViewController перестворюються: після свайпу з Recent Apps система відновлює Activity через SavedInstanceState, на iOS — при поверненні з фону після вивантаження ViewController через нестачу пам'яті. Часто розробники не враховують, що при warm start повторно викликається onCreate (Android) або viewDidLoad (iOS), і всі ініціалізації виконуються заново.
Warm start швидший за cold start (JVM/VM уже запущені, Application-код виконано), але повільніший за hot start, коли екран просто відновлюється зі стеку. Проблема в тому, що відновлення стану при warm start часто робиться неправильно: збереження великих об'єктів у Bundle, синхронні запити до БД, повторне створення HTTP-клієнтів. Ми гарантуємо прискорення warm start щонайменше на 50% за рахунок правильної архітектури — ViewModel з SavedStateHandle, кешування даних та єдиний синглтон-провайдер мережевих сервісів.
Як на Android уникнути проблем із SavedInstanceState?
Головна пастка warm start на Android — неправильна обробка SavedInstanceState. При знищенні Activity система викликає onSaveInstanceState, розробник зберігає дані, Activity перестворюється з savedInstanceState != null. Все добре — доки в Bundle не потрапляють великі об'єкти. Bundle не призначений для серіалізації великих даних — 500KB зображень у Bitmap або серіалізований список із 200 об'єктів викликають TransactionTooLargeException або тихий crash. Правило: у Bundle — тільки ID та minimal state, дані — у ViewModel, яка переживає перестворення Activity.
ViewModel з SavedStateHandle — правильний підхід: SavedStateHandle зберігає тільки ID/примітиви в Bundle, повні дані зберігаються в ViewModel.stateFlow, відновлюються з репозиторію по ID при необхідності. Наш досвід показує, що це скорочує час відновлення на 70%.
Важкі операції в onCreate при warm start — класична помилка. Розробник пише код для cold start, забуваючи що при warm start onCreate викликається знову. Ініціалізація Room, створення Retrofit-клієнта, запуск WorkManager — все це не повинно повторюватися при кожному onCreate. Dagger/Hilt @Singleton вирішує проблему для інфраструктурних компонентів, але за логікою ініціалізації потрібно стежити.
Чому State Restoration на iOS — слабке місце?
На iOS warm start відбувається при поверненні в застосунок після того, як ViewController був вивантажений через didReceiveMemoryWarning. viewDidLoad викликається знову, viewWillAppear теж. Проблема — якщо вся логіка ініціалізації екрану в viewDidLoad, вона виконається повторно: зробить зайві мережеві запити, перестворить UI, втратить позицію скролу.
UIKit State Restoration API (encodeRestorableState, decodeRestorableState) — правильний механізм, але використовується рідко через складність. Згідно з Apple State Restoration Programming Guide, використання encodeRestorableState дозволяє зберегти складні стани, але багато розробників віддають перевагу ручному підходу: збереження стану в UserDefaults або через Codable у файл.
SwiftUI краще справляється з цією проблемою через @StateObject та @AppStorage — state автоматично переживає перестворення View. Але при використанні UIKit-хостингу (UIHostingController) потрібно стежити, щоб не перестворювати @StateObject при кожному обгортанні.
Головна стаття втрат на iOS при warm start — повторні мережеві запити даних, які вже були завантажені до вивантаження. Правильний шар кешування в репозиторії (NSCache для in-memory, CoreData/Realm для persistence) дозволяє миттєво показати дані з кешу та оновити в фоні. Це дозволяє скоротити час до відмальовування на 60%.
Кейс: прискорення warm start в e-commerce з 1.8 до 0.4 секунди
У нашій практиці був проект інтернет-магазину з каталогом товарів. Warm start на mid-range Android займав 1.8 секунди. Profiler показав: 900мс — перестворення Retrofit/OkHttp клієнтів у Fragment.onCreateView, 400мс — синхронний запит до Room для завантаження категорій, 500мс — inflate складного RecyclerView layout.
Докладніше про кейс
Виправлення: Retrofit у `@Singleton` через Hilt, Room-запит перенесено в `ViewModel.init` з `viewModelScope.launch`, категорії закешовані in-memory з TTL 5 хвилин, layout спрощено з ViewBinding precompile. Підсумок: warm start 0.4 секунди — прискорення в 4.5 рази. Фінансова вигода від прискорення запуску проявилася у зниженні відмов користувачів на 15% та економії бюджету на підтримку серверної інфраструктури.Які інструменти використовувати для вимірювання?
Android: adb shell am start -W package/activity — показує TotalTime для warm start. Для детального аналізу — Perfetto з секцією ActivityThread.handleStartActivity. Firebase Performance Monitoring автоматично трекає startup traces у продакшені.
iOS: Instruments → Time Profiler з шаблоном App Launch. MetricKit в iOS 13+ збирає MXAppLaunchMetric з розбивкою на cold/warm/resume.
Типи запуску: cold warm hot
| Тип старту | Опис | Типовий час | Залежить від |
|---|---|---|---|
| Cold | Процесу немає, повна ініціалізація | >2с | Розмір застосунку, кількість класів |
| Warm | Процес живий, Activity/VC перестворюється | 0.5-2с | Складність відновлення стану |
| Hot | Activity/VC у пам'яті, просто показ | <0.1с | Тільки відмальовування |
Таблиця типових проблем та рішень
| Проблема | Рішення | Інструменти |
|---|---|---|
| Великі об'єкти в Bundle | Зберігати тільки ID, дані — у ViewModel | SavedStateHandle, ViewModel |
| Повторні мережеві запити | Кешування в Repository | NSCache, Room, CoreData |
| Повторне створення синглтонів | DI-контейнер | Dagger Hilt, Swinject |
| Важкий inflate layout | ViewBinding, Jetpack Compose | Precompile теги |
Процес роботи та що входить
- Аналітика — замір часу warm start на цільових пристроях, профілювання (Perfetto, Instruments).
- Проектування — архітектура відновлення стану, вибір інструментів кешування.
- Реалізація — рефакторинг ініціалізації, впровадження ViewModel/SavedStateHandle, кеш-шару.
- Тестування — на 5+ реальних пристроях, включаючи старі моделі.
- Документація — опис нового підходу для підтримки.
Відзначимо: Що входить у роботу:
- Аудит поточного часу warm start.
- Виявлення вузьких місць: повторні ініціалізації, важкі операції в onCreate/viewDidLoad.
- Рефакторинг: впровадження ViewModel, синглтонів, кешування.
- Тестування на реальних пристроях.
- Гарантія зниження часу warm start на 50%.
Ми — команда з 8-річним досвідом у мобільній розробці, реалізували понад 20 проектів з оптимізації продуктивності. Замовте аудит warm start вашого застосунку — ми проведемо профілювання та запропонуємо оптимізації під ключ протягом двох тижнів. Зв'яжіться з нами для оцінки проекту.







