Локальне зберігання даних у мобільних застосунках

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

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

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

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

Послуги, які ми пропонуємо
Показано 30 з 40Усі 1735 послуг
Розробка CMS для контенту мобільного додатку
Середній
від 1 тижня до 3 місяців
Розробка мобільного додатку для бібліотеки
Середній
від 1 тижня до 3 місяців
Часті запитання

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

Етапи розробки

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Локальне сховище в мобільних додатках: Core Data, Room, Realm, Hive, Isar

Додаток теряє дані при втраті мережі — і це не просто баг, це провал сценарію. Користувач заповнив форму, натиснув «Відправити», отримав таймаут і втратив усе. Або гірше: дані були відправлені двічі через неправильну логіку повторної відправки. Правильно вибране та налаштоване сховище вирішує цю проблему раз і назавжди.

Вибір бази даних — не питання смаку

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

Room (Android) — обгортка над SQLite з compile-time верифікацією SQL-запитів. Якщо запит невалідний, збірка падає — це краще, ніж SQLiteException в runtime. Room добре інтегрується з Kotlin Flow та LiveData, що робить реактивні UI-оновлення прямолінійними. Основна складність — міграції схеми. @Database(version = N, exportSchema = true) з файлами міграцій в assets/databases/ — обов'язкова практика, інакше при оновленні додатку fallbackToDestructiveMigration() просто сотре дані користувача.

Core Data (iOS) — не база даних, а фреймворк управління графом об'єктів поверх SQLite (або XML, або in-memory). NSPersistentContainer з viewContext для читання на main thread та newBackgroundContext() для запису — базова схема. Проблема починається, коли розробник робить save() в viewContext з фонового потоку: EXC_BAD_ACCESS в випадковий момент, відтворюється раз на тиждень, в краш-логу мало корисного. Необхідно використовувати performAndWait або perform для кожного контексту строго у своєму потоці.

Realm перемагає там, де потрібна швидкість роботи з великими наборами об'єктів та вбудована реактивність через Results + observe(). Realm зберігає об'єкти напряму, без маппингу ORM, тому читання не потребує десеріалізації. На Flutter Realm SDK (ex-MongoDB Realm) підтримує Device Sync — але це вже managed-сервіс з окремою інфраструктурою.

Hive та Isar — Flutter-специфічні рішення. Hive — key-value сховище, швидко, просто, підходить для налаштувань та кешів. Isar — повноцінна документо-орієнтована БД, написана на Rust, компілюється в нативний код. Для Flutter-додатків з offline-функціональністю Isar зараз краще: вбудований query builder з типобезпечними фільтрами, трансакції, watchObject/watchQuery для реактивності.

Платформа Рішення Реактивність Синхронізація
Android Room + Flow LiveData/Flow WorkManager
iOS Core Data NSFetchedResultsController CloudKit
Flutter Isar Streams Custom / Realm Sync
Cross-platform Realm RealmResults.observe Device Sync
Flutter (simple) Hive ValueListenable Немає

Offline-синхронізація — тут починається справжня складність

Локальне сховище саме по собі несклідне. Складність — у синхронізації з сервером при наявності конфліктів.

Найчастіший паттерн — optimistic updates з rollback. Користувач редагує запис, UI відображає змінення миттєво, фоновий запит йде на сервер. Якщо сервер повертає помилку — откатуємо локальний стейт. Виглядає просто. На практиці: якщо користувач встиг піти з екрана та повернутися, а откат відбувся через 3 секунди — UX зламаний. Потрібна явна черга операцій зі станом (PENDING, SYNCED, FAILED) в окремій таблиці.

На Android для фонової синхронізації користуємо WorkManager з Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED). Важливо не забути про setInputMerger(ArrayCreatingInputMerger::class) при батчингу задач — інакше при кількох одночасних запусках дані затираються.

На iOS аналог — BGTaskScheduler з BGProcessingTaskRequest. Обмеження iOS на фонове час виконання (~30 секунд для refresh tasks) означають, що синхронізація повинна бути інкрементальною: не «синхронізувати всё», а «синхронізувати наступні N записів, зберегти курсор».

Конфлікти при мультипристрійній роботі вирішуються одним з трьох підходів:

  • Last-write-wins по updated_at (найпростіший, теряє дані при одночасному редагуванні)
  • Server-wins (клієнт завжди приймає серверну версію)
  • Three-way merge (складно, потрібен спільний предок — підходить для документів)

У більшості B2C-додатків достатньо last-write-wins з вектором часу на рівні користувача, але при спільному редагуванні потрібен CRDTs-підхід — тоді дивимося на Automerge або Yjs з мобільними біндингами.

Як будуємо шар сховища

Репозиторний паттерн — не опціональний, а обов'язковий. UserRepository не знає, звідки дані: з Room, Realm або мережі. ViewModel викликає repository.getUser(id), отримує Flow/Stream, відображає дані. Логіка кеширування — всередині репозиторію.

Для Flutter типова архітектура: Isar для персистентності, Riverpod для управління станом, ConnectivityPlus для визначення стану мережі, кастомний SyncService з чергою операцій. Riverpod AsyncNotifier зручно покриває логіку «показати кеш, оновити з мережі, показати нові дані».

Окрема тема — шифрування. Якщо додаток зберігає медичні дані, платіжні карти або корпоративні документи, SQLCipher (Android) та NSFileProtection (iOS) — не опція. Realm підтримує шифрування нативно через ключ у 64 байта, який потрібно зберігати в Keychain/Keystore, а не в SharedPreferences.

Етапи роботи

Починаємо з аудиту вимог: які дані, який обсяг, потрібна ли синхронізація, можливі ли конфлікти. На цьому етапі стає ясно: Core Data або SQLite-based рішення, потрібен ли Realm Sync або хватить простого REST-поллінга.

Далі — проектування схеми з урахуванням міграцій. Схему змінюють у будь-якому проекті — питання не «будуть ли міграції», а «наскільки болісно вони пройдуть». Експортуємо схему в JSON, зберігаємо в репозиторії, пишемо тести на міграцію кожної версії.

Розробка йде з покриттям репозиторного шару юніт-тестами: моки сітьового шару, реальна in-memory база для тестування запитів. Перед релізом — профілювання запитів через Android Profiler (вкладка Database Inspector) або Core Data debug флаги (-com.apple.CoreData.SQLDebug 1).

Терміни для реалізації шару сховища з базовою offline-синхронізацією — від 2 до 6 тижнів залежно від складності схеми та вимог до конфлікт-резолюції.