Избегайте неоптимизированных загрузок

У некоторых пользователей вашего приложения нет постоянного доступа к интернету или есть ограничения на объем данных, которые они могут скачать на свои устройства. Вы можете побудить пользователей чаще взаимодействовать с вашим приложением, уменьшив объем данных, которые ему необходимо загрузить.

Самый простой способ сократить объем скачиваемых данных – скачивать только то, что вам нужно. Для этого нужно реализовать REST API, которые позволяют задавать критерии запроса, ограничивающие возвращаемые данные, например время последнего обновления.

Аналогично, при скачивании изображений рекомендуется уменьшать их размер на стороне сервера, а не скачивать полноразмерные изображения, которые уменьшаются на стороне клиента.

Кэшировать HTTP-ответы

Ещё один важный метод – избегать скачивания дублирующихся данных. Чтобы не скачивать одни и те же данные несколько раз, используйте кеширование. Кешируя данные и ресурсы приложения, вы создаете локальную копию информации, к которой приложению нужно обращаться. Если вашему приложению требуется доступ к одной и той же информации несколько раз за короткий период времени, вам нужно загрузить ее в кэш только один раз.

Чтобы уменьшить общий объем скачиваемых данных, важно как можно активнее использовать кеширование. Всегда кешируйте статические ресурсы, в том числе скачиваемые по запросу, например полноразмерные изображения, на максимально возможный срок. Ресурсы по запросу следует хранить отдельно, чтобы вы могли регулярно очищать кеш и управлять его размером.

Чтобы кеширование не приводило к показу устаревших данных в приложении, используйте подходящие коды статуса HTTP и заголовки, например ETag и Last-Modified. Это позволяет определить, когда следует обновить связанный контент. Пример:

// url represents the website containing the content to place into the cache.
val conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection
val currentTime: Long = System.currentTimeMillis()
val lastModified: Long = conn.getHeaderFieldDate("Last-Modified", currentTime)

// lastUpdateTime represents when the cache was last updated.
if (lastModified < lastUpdateTime) {
    // Skip update.
} else {
    // Parse update.
    lastUpdateTime = lastModified
}

Некоторые сетевые библиотеки можно настроить так, чтобы они автоматически учитывали эти коды статуса и заголовки. Например, если вы используете OkHttp, то, чтобы включить кеширование HTTP, вам нужно настроить каталог и размер кеша для клиента, как показано в примере кода ниже.

val cacheDir = context.getCacheDir()
val cacheSize = 10L * 1024L * 1024L // 10 MiB
val client: OkHttpClient = OkHttpClient.Builder()
    .cache(Cache(cacheDir, cacheSize))
    .build()

Если кеш настроен, вы можете обслуживать полностью кешированные HTTP-запросы непосредственно из локального хранилища, не открывая сетевое подключение. Ответы, кэшированные условно, могут проверять свою актуальность на сервере, что позволяет избежать затрат на скачивание. Ответы, которые не были кешированы, сохраняются в кеше ответов для будущих запросов.

Для кеширования неконфиденциальных данных в неуправляемом каталоге внешнего кеша используйте Context.getExternalCacheDir(). Вы также можете кешировать данные в управляемом безопасном кеше приложения с помощью Context.getCacheDir(). Обратите внимание, что этот внутренний кеш может быть очищен, если в системе заканчивается доступное хранилище.

Как использовать хранилище

Для более сложного подхода к кешированию рассмотрите шаблон проектирования Repository. Для этого создается специальный класс, называемый репозиторием, который предоставляет абстракцию API для определенных данных или ресурсов. Репозиторий может изначально получать данные из различных источников, таких как удаленный веб-сервис, но при последующих вызовах предоставляет вызывающим абонентам кэшированную версию данных. Этот уровень косвенности позволяет вам обеспечить надежную стратегию кэширования, специфичную для вашего приложения. Дополнительные сведения об использовании шаблона репозитория в вашем приложении см. в Руководстве по архитектуре приложений.