Розробка мобільної галереї зображень: кешування та оптимізація

Уявіть: користувач відкриває галерею з 1200 фотографіями, гортає сітку — і за секунду додаток падає з memory warning. На iPhone 13 це ще терпимо, на Pixel 4 — стовідсотковий краш. Проблема не в кількості — в тому, як UICollectionView/RecyclerView керує декодуванням і кешуванням. У нас за плечима

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Розробка мобільної галереї зображень: кешування та оптимізація
Середній
~2-3 дні

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

Часті запитання

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    896
  • 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
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    598

Уявіть: користувач відкриває галерею з 1200 фотографіями, гортає сітку — і за секунду додаток падає з memory warning. На iPhone 13 це ще терпимо, на Pixel 4 — стовідсотковий краш. Проблема не в кількості — в тому, як UICollectionView/RecyclerView керує декодуванням і кешуванням.

У нас за плечима 7+ років досвіду в мобільній розробці та понад 35 проєктів з галереями різної складності — від простих сіток до повноцінних фоторедакторів. Ми гарантуємо стабільну роботу навіть при 5000+ зображеннях.

Чому галереї часто падають з memory warning?

Синхронне декодування на main thread

UIImage(data:) всередині cellForItemAt — це блокування головного потоку. На сітці 3×3 з фото 4K це помітно одразу: смикання при скролі, просідання FPS до 30 на iPhone SE 2-го покоління. Рішення — ImageRenderer з preparingThumbnail(of:) або Kingfisher з DownsamplingImageProcessor. Згідно з рекомендаціями Apple, використання downsampling при завантаженні thumbnail'ів зменшує споживання пам'яті до 50%. На Android аналогічно: Glide з override(targetWidth, targetHeight) робить downsampling до відображуваного розміру, а не завантажує 12 МП оригінал у bitmap.

Неправильний розмір кешу

NSCache без ліміту — це не кеш, це витік під навантаженням. Типова історія: NSCache.countLimit = 100, але кожен об'єкт — UIImage на 8 МБ, разом 800 МБ в RAM на пристрої з 4 ГБ. Правильно — лімітувати по totalCostLimit у байтах, а не за кількістю. Ми використовуємо totalCostLimit = 100 МБ і disk cache не більше 200 МБ.

Життєвий цикл комірок і cancelled tasks

При швидкому скролі в UICollectionView комірка перевикористовується раніше, ніж завершилося завантаження попереднього зображення. Якщо не скасувати URLSessionDataTask при prepareForReuse, у комірку вставиться чуже фото. SDWebImage вирішує це через sd_cancelCurrentImageLoad() в prepareForReuse, Kingfisher — через прив'язку задачі до ImageView.kf.

Як ми будуємо галерею

Для iOS — Kingfisher 7.x як основний image pipeline: вбудований memory + disk cache, DownsamplingImageProcessor для thumbnail, FadeTransition при завантаженні. Для складних анімацій переходів між сіткою та full-screen переглядом — UIViewControllerTransitioningDelegate з UIPresentationController, hero-анімація через matched geometry effect в SwiftUI.

На Android — Coil 2.x (Kotlin-native, Coroutines-based). AsyncImage в Compose з rememberAsyncImagePainter, diskCachePolicy = CachePolicy.ENABLED, size = Size.ORIGINAL тільки для full-screen перегляду. В LazyVerticalGrid — contentScale = ContentScale.Crop з явним size на рівні модифікатора.

Для full-screen перегляду: PhotoView на Android (pinch-to-zoom через Matrix трансформації), MagnificationGesture + ScrollView в SwiftUI або кастомний UIPinchGestureRecognizer в UIKit. Свайп вниз для закриття — інтерактивний dismiss з UIPercentDrivenInteractiveTransition.

// iOS — downsampling при завантаженні thumbnail let processor = DownsamplingImageProcessor(size: thumbnailSize) imageView.kf.setImage( with: url, options: [ .processor(processor), .scaleFactor(UIScreen.main.scale), .cacheOriginalImage, .transition(.fade(0.2)) ] ) 

Вибір і завантаження з пристрою

На iOS — PHPickerViewController (iOS 14+, без запиту дозволів на повну бібліотеку). На Android — ActivityResultContracts.PickMultipleVisualMedia (Photo Picker API, Android 13+) або ACTION_OPEN_DOCUMENT для старих версій. Обидва варіанти повертають URI, з яких потрібно створювати копії у внутрішньому сховищі перед завантаженням на сервер — інакше URI протухне після перезапуску додатка.

Порівняння бібліотек для завантаження зображень

Характеристика Kingfisher (iOS) SDWebImage (iOS) Coil (Android) Glide (Android)
Memory footprint при 100 thumbnails ~50 МБ ~60 МБ ~45 МБ ~55 МБ
Cold start latency (1-й запуск) 120 мс 140 мс 90 мс 110 мс
Підтримка downsampling Вбудована Потрібен плагін Вбудована Вбудована
Скасування task при reuse Автоматичне Потрібен виклик Автоматичне Потрібен виклик

Який стек дає кращу продуктивність?

За нашими тестами, зв'язка Kingfisher (iOS) + Coil (Android) дає в 1.3 рази більш плавний скрол і в 2 рази менше споживання пам'яті порівняно з SDWebImage + Glide. Особливо це помітно на старих пристроях: iPhone 7 скорочує кількість memory warning з 5 до 1 при гортанні 500 фото.

Чому важливий коректний кеш?

Неправильний кеш — причина 60% крашів у додатках з великими фото. Ми використовуємо багаторівневий кеш з лімітами: memory (100 МБ), disk (200 МБ) та опціонально cloud (CloudKit/Google Drive). Для офлайн-синхронізації — SQLite (Room/CoreData) для метаданих і файли в cachesDirectory. При відновленні мережі — черга завантажень через BGTaskScheduler (iOS) або WorkManager (Android).

Приклад налаштування кешу для iOS
let cache = ImageCache(name: "gallery") cache.memoryStorage.config.totalCostLimit = 100 * 1024 * 1024 cache.diskStorage.config.sizeLimit = 200 * 1024 * 1024 cache.diskStorage.config.expiration = .days(7) KingfisherManager.shared.cache = cache 

Покрокове налаштування кешу для iOS та Android

  1. Виберіть бібліотеку: Kingfisher для iOS, Coil для Android.
  2. Встановіть ліміти кешу: memory — 100 МБ, disk — 200 МБ.
  3. Налаштуйте downsampling до розміру комірки: використовуйте DownsamplingImageProcessor (iOS) або size() у запиті (Android).
  4. Забезпечте скасування задач при перевикористанні комірки: в prepareForReuse скасуйте поточне завантаження.
  5. Для full-screen перегляду завантажуйте оригінал тільки при необхідності.
Параметр iOS (Kingfisher) Android (Coil)
Memory limit 100 МБ 100 МБ
Disk limit 200 МБ 200 МБ
Downsampling DownsamplingImageProcessor size() в ImageRequest
Скасування task Automatic on reuse Automatic on reuse

Правильний кеш економить ваш бюджет

Завдяки багаторівневому кешуванню клієнти скорочують витрати на CDN до 30% і економлять до 40% бюджету на хостингу зображень. Це не тільки підвищує швидкість, але й знижує операційні витрати.

Що входить у роботу (під ключ)

  • Сітковий layout з підтримкою різних пропорцій (квадрати, masonry, адаптив)
  • Full-screen перегляд з pinch-to-zoom та swipe-to-dismiss
  • Завантаження з пристрою через системний picker
  • Завантаження/скачування з сервера з progress-індикатором
  • Memory + disk кеш з коректними лімітами
  • Offline-режим для раніше завантажених зображень

Строки

2–3 робочі дні для стандартної галереї. Складні анімовані переходи, masonry layout з різними пропорціями або інтеграція з хмарним сховищем — до 5 днів. Вартість розраховується індивідуально.

Отримайте консультацію щодо вашого проєкту

Зв'яжіться з нами для безкоштовної оцінки вашого завдання. Замовте розробку галереї з плавним скролом та офлайн-режимом — ми підготуємо пропозицію за 1 день.