Evitar downloads não otimizados

Alguns dos usuários do seu app têm acesso intermitente à Internet ou têm limites na quantidade de informações que podem ser transferidas por download para os dispositivos. Você pode incentivar os usuários a interagir com seu app com mais frequência reduzindo a quantidade de dados que ele precisa transferir por download.

A maneira mais básica de reduzir seus downloads é fazer apenas o que você precisa. Em termos de dados, isso significa implementar APIs REST que permitem especificar critérios de consulta que limitam os dados retornados usando parâmetros como o horário da última atualização.

Da mesma forma, ao fazer o download de imagens, é uma prática recomendada reduzir o tamanho delas no lado do servidor, em vez de fazer o download de imagens em tamanho original que são reduzidas no cliente.

Armazenar respostas HTTP em cache

Outra técnica importante é evitar o download de dados duplicados. É possível reduzir a probabilidade de fazer o download dos mesmos dados repetidamente usando o armazenamento em cache. Ao armazenar em cache os dados e recursos do app, você cria uma cópia local das informações que o app precisa referenciar. Se o app precisar acessar a mesma informação várias vezes em um curto período, você precisará fazer o download dela no cache apenas uma vez.

É importante armazenar em cache o mais agressivamente possível para reduzir a quantidade total de dados transferidos por download. Sempre armazene em cache recursos estáticos, incluindo downloads sob demanda, como imagens em tamanho original, pelo maior tempo possível possível. Os recursos sob demanda precisam ser armazenados separadamente para que você esvazie seu cache sob demanda regularmente para gerenciar o tamanho dele.

Para garantir que o armazenamento em cache não resulte na exibição de dados desatualizados no app, use os códigos e cabeçalhos de status HTTP adequados, como os cabeçalhos ETag e Last-Modified. Isso permite determinar quando o conteúdo associado precisa ser atualizado. Por exemplo:

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;
}

É possível configurar algumas bibliotecas de rede para respeitar esses cabeçalhos e códigos de status automaticamente. Ao usar OkHttp, por exemplo, configurar um diretório e um tamanho de cache para o cliente permitirá que a biblioteca use o armazenamento em cache HTTP, conforme mostrado no exemplo de código a seguir:

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

Com o cache configurado, é possível atender a solicitações HTTP totalmente armazenadas em cache diretamente do armazenamento local, eliminando a necessidade de abrir uma conexão de rede. As respostas armazenadas em cache condicionalmente podem validar a atualização delas no servidor, eliminando o custo de largura de banda associado ao download. As respostas sem cache são armazenadas no cache de resposta para solicitações futuras.

É possível armazenar dados não confidenciais no diretório de cache externo não gerenciado usando Context.getExternalCacheDir(). Como alternativa, é possível armazenar dados no cache gerenciado e seguro do aplicativo usando Context.getCacheDir(). Esse cache interno poderá ser limpo quando o sistema estiver com pouco armazenamento disponível.

Usar um repositório

Para uma abordagem mais sofisticada de armazenamento em cache, considere o padrão de design do repositório. Isso envolve a criação de uma classe personalizada, conhecida como repositório, que fornece uma abstração da API sobre alguns dados ou recursos específicos. Inicialmente, o repositório pode buscar os dados de várias fontes, como um serviço da Web remoto, mas fornece aos autores da chamada uma versão dos dados em cache nas chamadas seguintes. Essa camada de indireção permite fornecer uma estratégia de armazenamento em cache robusta e específica para o app. Para mais informações sobre como usar o padrão de repositório no app, consulte o Guia para a arquitetura do app.