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

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

Самый простой способ сократить количество загружаемых данных — это скачивать только то, что вам нужно. В контексте данных это означает внедрение 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
}

Java

// url represents the website containing the content to place into the cache.
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
long currentTime = System.currentTimeMillis();
long lastModified = 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()

Java

File cacheDir = Context.getCacheDir();
long cacheSize = 10L * 1024L * 1024L; // 10 MiB
OkHttpClient client = new OkHttpClient.Builder()
    .cache(new Cache(cacheDir, cacheSize))
    .build();

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

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

Используйте репозиторий

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