У некоторых пользователей вашего приложения может быть нестабильный доступ к интернету или ограничения на объем данных, которые они могут скачать на свои устройства. Вы можете побудить пользователей чаще взаимодействовать с вашим приложением, уменьшив объем данных, которые ему необходимо загрузить.
Самый простой способ сократить объем скачиваемых данных – скачивать только то, что вам нужно. Для этого нужно реализовать REST API, которые позволяют задавать критерии запроса, ограничивающие возвращаемые данные, с помощью таких параметров, как время последнего обновления.
Аналогично, при скачивании изображений рекомендуется уменьшать их размер на стороне сервера, а не скачивать полноразмерные изображения, которые уменьшаются на стороне клиента.
Кеширование HTTP-ответов
Ещё один важный метод – избегать скачивания дублирующихся данных. Чтобы не скачивать одни и те же данные несколько раз, используйте кеширование. Кешируя данные и ресурсы приложения, вы создаете локальную копию информации, к которой приложению нужно обращаться. Если вашему приложению требуется доступ к одной и той же информации несколько раз за короткий период времени, вам нужно загрузить ее в кэш только один раз.
Важно кэшировать как можно больше данных, чтобы уменьшить общий объем скачиваемых данных. Всегда кешируйте статические ресурсы, в том числе скачиваемые по запросу, например полноразмерные изображения, на максимально возможный срок. Ресурсы по запросу следует хранить отдельно, чтобы вы могли регулярно очищать кеш и управлять его размером.
Чтобы кеширование не приводило к показу устаревших данных в приложении, используйте подходящие коды статуса HTTP и заголовки, например ETag и Last-Modified. Это позволяет определить, когда следует обновить связанный контент. Пример:
Kotlin
// 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, как показано в следующем примере кода:
Kotlin
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().
Обратите внимание, что этот внутренний кеш может быть очищен, если в системе заканчивается доступное хранилище.
Использовать хранилище
Для более сложного подхода к кешированию рассмотрите шаблон проектирования Repository. Для этого нужно создать собственный класс, называемый репозиторием, который предоставляет абстракцию API для определенных данных или ресурсов. Репозиторий может изначально получать данные из различных источников, например из удаленного веб-сервиса, но при последующих вызовах предоставляет вызывающим абонентам кэшированную версию данных. Этот уровень косвенности позволяет вам предоставить надежную стратегию кэширования, специфичную для вашего приложения. Дополнительные сведения об использовании шаблона репозитория в вашем приложении см. в Руководстве по архитектуре приложений.