Otimizar o acesso à rede

O uso do rádio sem fio para transferir dados é, possivelmente, uma das fontes mais significativas de consumo de bateria do seu app. Para minimizar o consumo de bateria associado à atividade de rede, é essencial entender como seu modelo de conectividade afetará o hardware de rádio subjacente.

Esta seção apresenta a máquina de estado de rádio sem fio e explica como o modelo de conectividade do seu app interage com ela. Ela oferece várias técnicas que, quando seguidas, ajudam a minimizar o efeito do consumo de dados do app na bateria.

A máquina de estado de rádio

O rádio sem fio do dispositivo do usuário tem recursos de economia de energia integrados que ajudam a minimizar a quantidade de energia consumida. Quando está totalmente ativo, o rádio sem fio consome uma quantidade significativa de energia, mas, quando inativo ou em espera, o rádio consome pouca energia.

É importante lembrar que o rádio não pode passar do modo de espera para totalmente ativo instantaneamente. Há um período de latência associado à "ativação" do rádio. Assim, a bateria transita de estados de maior energia para estados de energia mais baixos lentamente, a fim de economizar energia quando não está em uso enquanto tenta minimizar a latência associada ao "carregamento" do rádio.

A máquina de estado para um rádio de rede 3G geralmente consiste em três estados de energia:

  • Potência total: usada quando uma conexão está ativa, permitindo que o dispositivo transfira dados na taxa mais alta possível.
  • Baixa energia: um estado intermediário que reduz o consumo de energia da bateria em cerca de 50%.
  • Em espera: o estado mínimo de consumo de energia em que nenhuma conexão de rede fica ativa.

Embora os estados de baixa potência e em espera consumam muito menos bateria, eles também introduzem uma latência considerável nas solicitações de rede. Retornar à potência total a partir do estado baixo leva cerca de 1,5 segundo, e a mudança do modo de espera para a potência total pode levar mais de dois segundos.

Para minimizar a latência, a máquina de estado usa um atraso para adiar a transição para estados de energia mais baixos. A Figura 1 usa os horários da AT&T para um rádio 3G típico.


Figura 1. Máquina de estado de rádio sem fio 3G típica.

A máquina de estado de rádio em cada dispositivo, especialmente o atraso de transição associado ("tempo de cauda") e a latência de inicialização, varia de acordo com a tecnologia de rádio sem fio empregada (3G, LTE, 5G e assim por diante) e é definida e configurada pela rede da operadora em que o dispositivo opera.

Esta página descreve uma máquina de estado representativa para um rádio sem fio 3G típico, com base nos dados fornecidos pela AT&T. No entanto, os princípios gerais e as práticas recomendadas resultantes são aplicáveis a todas as implementações de rádio sem fio.

Essa abordagem é particularmente eficaz para a navegação na Web para dispositivos móveis típica, porque evita latência indesejada enquanto os usuários navegam na Web. O tempo de cauda relativamente baixo também garante que, quando uma sessão de navegação terminar, o rádio possa passar para um estado de energia mais baixo.

Infelizmente, essa abordagem pode levar a apps ineficientes em sistemas operacionais modernos de smartphones, como o Android, em que os apps são executados em primeiro plano (em que a latência é importante) e em segundo plano (em que a duração da bateria precisa ser priorizada).

Como os apps afetam a máquina de estado de rádio

Cada vez que você cria uma nova conexão de rede, o rádio transita para o estado de potência total. No caso da máquina de estado de rádio 3G típica descrita anteriormente, ela permanecerá em potência total durante a transferência, mais 5 segundos extras de tempo de cauda, seguidos por 12 segundos no estado de baixa energia. Assim, para um dispositivo 3G típico, cada sessão de transferência de dados fará com que o rádio consuma energia por pelo menos 18 segundos.

Na prática, isso significa que um app que faz uma transferência de dados de um segundo, três vezes por minuto, vai manter o rádio sem fio sempre ativo, movendo-o de volta para a alta potência assim que ele entra no modo de espera.


Figura 2. Uso relativo de energia de rádio sem fio para transferência de um segundo executada três vezes a cada minuto. A figura exclui a latência de "carregamento" entre execuções.

Em comparação, se o mesmo app agrupasse as transferências de dados e executasse uma única transferência de três segundos a cada minuto, isso manteria o rádio no estado de alta potência por apenas 20 segundos por minuto. Isso permitiria que o rádio ficasse em espera por 40 segundos a cada minuto, resultando em uma redução significativa no consumo de bateria.


Figura 3. Uso relativo de energia de rádio sem fio para transferências de três segundos executadas uma vez por minuto.

Técnicas de otimização

Agora que você entende como o acesso à rede afeta a duração da bateria, vamos falar sobre algumas ações que podem ser feitas para reduzir o consumo da bateria e oferecer uma experiência do usuário rápida e fluida.

Transferências de dados em pacote

Conforme mencionado na seção anterior, agrupar suas transferências de dados para que você transfira mais dados com menos frequência é uma das melhores maneiras de melhorar a eficiência da bateria.

Obviamente, isso nem sempre é possível se o app precisar receber ou enviar dados imediatamente em resposta a uma ação do usuário. É possível atenuar isso antecipando e fazendo a pré-busca de dados. Outros cenários, como o envio de registros ou análises para um servidor e outras transferências de dados não urgentes iniciadas pelo app, funcionam muito bem com lotes e agrupamentos. Consulte Como otimizar tarefas iniciadas pelo app para conferir dicas sobre como programar transferências de rede em segundo plano.

Fazer pré-busca de dados

A pré-busca de dados é outra maneira eficaz de reduzir o número de sessões independentes de transferência de dados executadas pelo app. Com a pré-busca, quando o usuário realiza uma ação no app, o app prevê quais dados provavelmente serão necessários para a próxima série de ações e busca esses dados em um único burst, em uma única conexão, com capacidade total.

Ao carregar suas transferências, você reduz o número de ativações de rádio necessárias para fazer o download de dados. Como resultado, você não apenas conserva a duração da bateria, como também melhora a latência, diminui a largura de banda necessária e reduz os tempos de download.

A pré-busca também oferece uma experiência do usuário aprimorada, minimizando a latência no app causada pela espera da conclusão dos downloads antes de executar uma ação ou visualizar dados.

Aqui está um exemplo prático.

Um leitor de notícias

Muitos apps de notícias tentam reduzir a largura de banda fazendo o download de manchetes só depois de uma categoria ser selecionada, de artigos completos apenas quando o usuário quer lê-los e de miniaturas assim que elas são exibidas na tela.

Com essa abordagem, o rádio é forçado a permanecer ativo para a maioria das sessões de leitura de notícias dos usuários enquanto eles rolam as manchetes, mudam de categoria e leem artigos. Não só isso, a troca constante entre estados de energia resulta em latência significativa ao trocar de categoria ou ler artigos.

Uma abordagem melhor é fazer a pré-busca de uma quantidade razoável de dados na inicialização, começando com o primeiro conjunto de manchetes e miniaturas, garantindo um tempo de inicialização de baixa latência, e continuando com as manchetes e miniaturas restantes, bem como o texto de cada artigo disponível pelo menos na lista de manchetes principais.

Outra alternativa é fazer a pré-busca de todas as manchetes, miniaturas, textos de artigos e possivelmente até fotos de artigos completos, normalmente em segundo plano em um horário predeterminado. Como essa abordagem corre o risco de consumir uma quantidade significativa de largura de banda e duração da bateria para fazer o download de conteúdo que nunca será usado, implemente-a com cuidado.

Outras considerações

Embora a pré-busca de dados tenha muitos benefícios, se usada muito agressivamente, a pré-busca também apresenta o risco de aumentar o consumo de bateria e a largura de banda, bem como a cota de download, ao fazer o download de dados que não são usados. Também é importante garantir que a pré-busca não atrase a inicialização do app enquanto ele aguarda a conclusão da pré-busca. Em termos práticos, isso pode significar o processamento progressivo de dados ou a priorização de transferências consecutivas, de modo que os dados necessários para a inicialização do aplicativo sejam transferidos por download e processados primeiro.

A intensidade com que você faz a pré-busca de dados depende do tamanho dos dados que estão sendo transferidos e da probabilidade de serem usados. Como um guia aproximado, com base na máquina de estado descrita anteriormente, para dados com 50% de chance de serem usados na sessão atual do usuário, normalmente é possível fazer a pré-busca por cerca de seis segundos (aproximadamente de 1 a 2 megabytes) antes que o custo potencial de fazer o download de dados não utilizados corresponda à possível economia de não fazer o download desses dados.

De modo geral, uma prática recomendada é pré-buscar dados de maneira que você só precise iniciar outro download a cada 2 a 5 minutos e na ordem de 1 a 5 megabytes.

Seguindo esse princípio, downloads grandes, como arquivos de vídeo, precisam ser feitos em blocos em intervalos regulares (a cada dois a cinco minutos), fazendo a pré-busca apenas dos dados de vídeo que provavelmente serão visualizados nos próximos minutos.

Uma solução é programar que o download completo ocorra apenas quando o dispositivo estiver conectado ao Wi-Fi e, possivelmente, apenas quando estiver carregando. A API WorkManager oferece suporte exatamente a esse caso de uso, o que permite restringir o trabalho em segundo plano até que o dispositivo atenda aos critérios especificados pelo desenvolvedor, como carregamento e conexão Wi-Fi.

Verifique a conectividade antes de fazer solicitações

A pesquisa por um sinal de celular é uma das operações que mais consome energia em um dispositivo móvel. Uma prática recomendada para solicitações iniciadas pelo usuário é verificar primeiro se há uma conexão usando ConnectivityManager, conforme mostrado em Monitorar o status da conectividade e a medição da conexão. Se não houver rede, o app poderá economizar bateria ao não forçar o rádio móvel a pesquisar. A solicitação pode ser programada e realizada em um lote com outras solicitações quando uma conexão é feita.

Conexões do pool

Outra estratégia que pode ser útil, além do agrupamento em lote e da pré-busca, é agrupar as conexões de rede do app.

Geralmente, é mais eficiente reutilizar conexões de rede do que iniciar novas. A reutilização de conexões também permite que a rede reaja de maneira mais inteligente ao congestionamento e a problemas de dados de rede relacionados.

O HttpURLConnection e a maioria dos clientes HTTP, como OkHttp, ativa o pool de conexões por padrão e reutiliza a mesma conexão para várias solicitações.

Recapitulação e análise para o futuro

Nesta seção, você aprendeu muito sobre o rádio sem fio e algumas estratégias que podem ser aplicadas amplamente para fornecer uma experiência do usuário rápida e responsiva, reduzindo o consumo de bateria.

Na próxima seção, vamos conhecer em detalhes três tipos distintos de interações de rede, comuns na maioria dos apps. Você vai aprender os impulsionadores de cada um desses tipos, bem como técnicas modernas e APIs para gerenciar essas interações de forma eficiente.