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. Ele 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 no dispositivo do usuário tem recursos integrados de economia de energia que ajudam a minimizar a quantidade de bateria que ele consome. Quando totalmente ativo, o rádio sem fio consome uma quantidade significativa de energia, mas, quando inativo ou em espera, ele consome muito pouca energia.

Um fator importante a se lembrar é que o rádio não pode passar da espera para a ativação total instantaneamente. Há um período de latência associado ao "ligamento" do rádio. Assim, a bateria transita de estados de energia mais altos para estados de energia mais baixos lentamente para economizar energia quando não está em uso, ao mesmo tempo em que 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 potência: um estado intermediário que reduz o consumo de energia da bateria em cerca de 50%.
  • Em espera: o estado de consumo mínimo de energia durante o qual nenhuma conexão de rede está 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 2 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, principalmente 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 está operando.

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 em dispositivos móveis comuns, porque impede a latência indesejada enquanto os usuários navegam. O tempo de cauda relativamente baixo também garante que, quando uma sessão de navegação é concluída, o rádio pode mudar 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, toda 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 exatamente quando ele estiver entrando no modo de espera.


Figura 2. Uso relativo de energia do rádio sem fio para transferências de um segundo em execução três vezes a cada minuto. A figura exclui a latência de "power up" entre as execuções.

Em comparação, se o mesmo app agrupasse as transferências de dados, executando uma única transferência de três segundos a cada minuto, isso manteria o rádio no estado de alta potência por um total de apenas 20 segundos a cada 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 em rádio sem fio para transferências de três segundos executadas uma vez a cada minuto.

Técnicas de otimização

Agora que você entende como o acesso à rede afeta a duração da bateria, vamos falar sobre algumas coisas que você pode fazer para reduzir o consumo de bateria, além de oferecer uma experiência de usuário rápida e fluida.

Transferências de dados de pacote

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

É claro que isso nem sempre é possível se o app precisa receber ou enviar dados imediatamente em resposta a uma ação do usuário. É possível atenuar isso antecipando e pré-buscando dados. Outros cenários, como o envio de registros ou análises para um servidor e outras transferências de dados não urgentes e iniciadas pelo app, são ideais para lotes e agrupamento. Consulte Como otimizar tarefas iniciadas pelo app para 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 que o app executa. 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 uma única sequência, 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 melhorada, minimizando a latência no app causada pela espera da conclusão dos downloads antes de executar uma ação ou visualizar os 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.

Usando 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 pelas manchetes, mudam de categoria e lêem artigos. Além disso, 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 de notícias, garantindo um tempo de inicialização de baixa latência, e continuando com as manchetes e miniaturas restantes, bem como o texto do artigo para 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 traga muitos benefícios, se usada de forma muito agressiva, ela também apresenta o risco de aumentar o consumo de bateria e o uso de 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 o término 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 app sejam transferidos e processados primeiro.

O nível de agressividade para fazer a pré-busca depende do tamanho dos dados a serem transferidos e da probabilidade de eles serem usados. Como orientação geral, com base na máquina de estado descrita anteriormente, para dados que têm 50% de chance de serem usados na sessão atual do usuário, normalmente é possível fazer a pré-busca por cerca de 6 segundos (aproximadamente 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 transferidos em blocos em intervalos regulares (a cada 2 a 5 minutos), realizando 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 é compatível exatamente com esse caso de uso, permitindo que você restrinja o trabalho em segundo plano até que o dispositivo atenda aos critérios especificados pelo desenvolvedor, como carregar e conectar-se ao Wi-Fi.

Verificar a conectividade antes de fazer solicitações

A pesquisa por um sinal de celular é uma das operações que mais consomem 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 de conexões. 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 lote com outras solicitações quando uma conexão é estabelecida.

Conexões de pool

Uma estratégia adicional que pode ajudar além do agrupamento e da pré-busca é agrupar as conexões de rede do app.

Geralmente, é mais eficiente reutilizar as conexões de rede existentes 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 o OkHttp, ativam o pooling de conexões por padrão e reutilizam a mesma conexão para várias solicitações.

Recapitulação e perspectiva do futuro

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

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