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

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

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

Ява

// 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()

Ява

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 для определенных данных или ресурсов. Репозиторий может изначально извлекать данные из различных источников, например, из удаленной веб-службы, но при последующих вызовах предоставлять вызывающим сторонам кэшированную версию данных. Этот уровень косвенности позволяет реализовать надежную стратегию кэширования, специфичную для вашего приложения. Подробнее об использовании шаблона «Репозиторий» в вашем приложении см. в Руководстве по архитектуре приложения .