Os usuários esperam que os apps sejam responsivos e rápidos para carregar. Um app com tempo de inicialização lento não atende a essa expectativa e pode ser decepcionante para os usuários. Esse tipo de experiência ruim pode fazer com que o usuário dê uma classificação negativa ao seu app na Play Store ou até mesmo desista de usá-lo.
Este documento fornece informações para ajudar a otimizar o tempo de inicialização do seu app. Ele começa explicando os aspectos internos do processo de inicialização. Em seguida, ele mostra como analisar o desempenho da inicialização. Por fim, descreve alguns problemas comuns no tempo de inicialização e dá algumas dicas sobre como resolvê-los.
Entender os diferentes estados de inicialização do app
A inicialização de um app pode ocorrer em um de três estados: inicialização a frio, inicialização com estado salvo ou inicialização a quente. Cada um desses estados afeta o tempo que leva para o app ficar visível para o usuário. Em uma inicialização a frio, o app é iniciado do zero. Nos outros estados, o sistema precisa levar o app que está em execução em segundo plano para o primeiro plano. Recomendamos que você sempre otimize presumindo que se trate de uma inicialização a frio. Ao fazer isso, o desempenho de inicializações a quente e com estado salvo também pode melhorar.
Para otimizar seu app para uma inicialização rápida, vale a pena entender o que está acontecendo nos níveis do sistema e do app e como eles interagem em cada um desses estados.
Inicialização a frio
Uma inicialização a frio refere-se a um app que é inicializado do zero: o processo do sistema, até a inicialização, não criou o processo do app. As inicializações a frio acontecem em casos em que o app é iniciado pela primeira vez desde que o dispositivo foi inicializado ou quando o sistema o eliminou. Esse tipo de inicialização apresenta o maior desafio em termos de minimizar o tempo de inicialização, porque o sistema e o app têm mais trabalho a fazer do que nos outros estados de inicialização.
No início de uma inicialização a frio, o sistema tem três tarefas. São elas:
- Carregamento e inicialização do app.
- Exibição de uma janela de inicialização em branco para o app imediatamente após o início.
- Crie o processo do app.
Assim que é criado pelo sistema, o processo do app fica responsável pelas próximas etapas:
- Criação do objeto do app.
- Inicialização da linha de execução principal.
- Criação da atividade principal.
- Aumento das visualizações.
- Definição do layout da tela.
- Execução do desenho inicial.
Depois que o processo do app conclui o primeiro desenho, o processo do sistema substitui a janela de segundo plano exibida no momento pela atividade principal. Nesse ponto, o usuário pode começar a usar o app.
A figura 1 mostra como os processos do sistema e do app transferem o trabalho entre si.

Problemas de desempenho podem surgir durante a criação do app e da atividade.
Criação do app
Quando o aplicativo é iniciado, a janela inicial em branco permanece na tela até o sistema concluir o desenho do app pela primeira vez. Nesse ponto, o processo do sistema substitui a janela inicial do app, permitindo que o usuário comece a interagir com o app.
Se você substituiu
Application.onCreate()
no seu próprio app, o sistema invoca o método onCreate()
no
objeto do app. Depois, o app gera a linha de execução principal (também conhecida como linha de execução
da UI) e a encarrega de criar sua atividade principal.
A partir desse ponto, os processos no nível do sistema e do app prosseguem de acordo com os estágios do ciclo de vida do app.
Criação da atividade
Depois que o processo do app cria sua atividade, ela executa as seguintes operações:
- Inicialização de valores.
- Chamada de construtores.
- Chama o método de callback, por exemplo,
Activity.onCreate()
, apropriado para o estado atual do ciclo de vida da atividade.
Normalmente, o método
onCreate()
tem o maior impacto no tempo de carregamento, porque executa o trabalho com
maior overhead: carrega e infla visualizações e inicializa os objetos
necessários para a execução da atividade.
Inicialização com estado salvo
Uma inicialização com estado salvo inclui um subconjunto das operações que acontecem durante uma inicialização a frio. Ao mesmo tempo, ela representa mais sobrecarga do que uma inicialização a quente. Há muitos estados em potencial que podem ser considerados inicialização com estado salvo. Por exemplo:
O usuário sai do app e depois o reinicializa. O processo pode ter continuado a ser executado, mas o app precisa recriar a atividade do zero fazendo uma chamada para
onCreate()
.O sistema elimina seu app da memória e, em seguida, o usuário o reinicializa. O processo e a atividade precisam ser reiniciados, mas a tarefa pode se beneficiar um pouco do pacote de estado da instância salvo, transmitido para
onCreate()
.
Inicialização a quente
Uma inicialização a quente do app é muito mais simples e com menos sobrecarga que uma inicialização a frio. Nesse tipo de inicialização, o sistema simplesmente leva sua atividade para o primeiro plano. Se todas as atividades do seu app ainda estiverem na memória, o app poderá evitar a repetição da inicialização, a inflação do layout e renderização de objetos.
No entanto, se alguma memória tiver sido limpa em resposta a eventos de corte de memória,
como
onTrimMemory()
,
esses objetos precisarão ser recriados em resposta ao evento de inicialização a quente.
Uma inicialização a quente exibe o mesmo comportamento na tela que o do cenário de uma inicialização a frio:
O processo do sistema mostra uma tela em branco até que o app termine de renderizar a atividade.

Usar métricas para detectar e diagnosticar problemas
Para diagnosticar adequadamente o desempenho dos tempos de inicialização, você pode rastrear métricas que mostram o tempo necessário para que o app seja iniciado. O Android oferece vários meios de informar que seu app está com um problema e ajudar a diagnosticá-lo. O recurso "Android vitals" pode alertar que o problema está ocorrendo, e as ferramentas de diagnóstico podem ajudar a diagnosticar o problema.
Benefícios do uso de métricas de inicialização
O Android usa as métricas Tempo para exibição inicial e Tempo para exibição total para otimizar as inicializações de app a frio e com estado salvo. O Android Runtime (ART) usa os dados dessas métricas para pré-compilar de forma eficiente o código e assim otimizar futuras inicializações.
Inicializações mais rápidas levam a uma interação mais consistente com o app, o que reduz as instâncias de saída antecipada, a reinicialização da instância ou a saída para outro app.
Android vitals
O Android vitals pode ajudar a melhorar o desempenho do seu app, mostrando alertas no Play Console quando o app exceder os tempos de execução. O Android vitals considera os tempos de inicialização do app excessivos quando:
- a inicialização a frio do app leva 5 segundos ou mais;
- a inicialização com estado salvo leva 2 segundos ou mais;
- a inicialização a quente leva 1,5 segundo ou mais.
O Android vitals usa a métrica Tempo para exibição inicial. Para ver informações sobre como o Google Play coleta dados do Android vitals, consulte a documentação do Play Console.
Tempo para exibição inicial
A métrica de tempo para exibição inicial (TTID, na sigla em inglês) mede o tempo que um aplicativo leva para produzir o primeiro frame, incluindo a inicialização do processo (se for uma inicialização a frio), a criação de atividades (se for a frio/com estado salvo) e a exibição do primeiro frame.
Como recuperar o TTID
No Android 4.4 (API de nível 19) ou versões mais recentes, o logcat inclui uma linha de saída
que contém um valor chamado Displayed
. Esse valor representa o tempo total
decorrido entre o início do processo e o término do desenho da atividade
correspondente na tela. O tempo decorrido abrange a seguinte sequência de
eventos:
- Início do processo.
- Inicialização dos objetos.
- Criação e inicialização da atividade.
- Inflação do layout.
- Desenho do app pela primeira vez.
A linha de registro informada é semelhante a este exemplo:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
Se você estiver rastreando a saída do logcat na linha de comando ou em um terminal, será fácil encontrar o tempo decorrido. Para encontrá-lo no Android Studio, é preciso desativar os filtros na visualização do logcat. A desativação dos filtros é necessária porque o servidor do sistema, não o app em si, atende a esse registro.
Depois de definir as configurações adequadas, você pode pesquisar facilmente o termo
correto para conferir o tempo. A Figura 2 mostra como desativar filtros e, na
segunda linha de saída da parte de baixo, um exemplo de saída do Logcat do
tempo Displayed
.

A métrica Displayed
na saída do Logcat não captura necessariamente
o tempo total até que todos os recursos sejam carregados e mostrados. Ela exclui
os recursos que não são referenciados no arquivo de layout ou que o app cria
como parte da inicialização do objeto. Ela exclui esses recursos, porque o carregamento
deles é um processo inline e não bloqueia a exibição inicial do app.
Às vezes, a linha Displayed
na saída do logcat contém um outro campo para o
tempo total. Exemplo:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
Nesse caso, a primeira medição de tempo é apenas da atividade que foi desenhada
pela primeira vez. A medição do tempo total
começa no início do processo do app e pode
incluir outra atividade que foi iniciada primeiro, mas não foi exibida
na tela. A medição de tempo total
só é exibida quando há
uma diferença entre tempo de inicialização da atividade individual e o total.
Você também pode medir o tempo para a exibição inicial executando seu app com o comando de Gerenciador de atividades do shell do adb. Veja um exemplo:
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN</pre>
A métrica Displayed
aparece na saída do logcat como antes. A janela do
terminal também exibe o seguinte:
Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete
Os argumentos -c
e -a
são opcionais e permitem especificar
<category>
e <action>
.
Tempo para exibição total
A métrica "Tempo para exibição total" (TTFD, na sigla em inglês) mede o tempo que o aplicativo leva para produzir o primeiro frame com conteúdo completo, incluindo o conteúdo carregado de forma assíncrona após o primeiro frame. Em geral, esse é o conteúdo da lista principal carregado pela rede, conforme relatado pelo app.
Como recuperar o TTFD
Você pode usar o método
reportFullyDrawn()
para medir o tempo decorrido entre a inicialização do app e a exibição
completa de todos os recursos e das hierarquias de visualização. Isso pode ser valioso nos casos
em que um app executa carregamento lento. No carregamento lento, um app não bloqueia o
desenho inicial da janela, mas carrega recursos de forma assíncrona e
atualiza a hierarquia de visualização.
Se, devido ao carregamento lento, a exibição inicial de um app não incluir todos os recursos, considere o carregamento e a exibição completos de todos os recursos e visualizações como uma métrica separada. Por exemplo, sua IU pode estar totalmente carregada, com algum texto desenhado, mas ainda não exibe imagens que o app precisa buscar na rede.
Para resolver esse problema, chame reportFullyDrawn()
manualmente para informar ao
sistema que sua atividade foi concluída com o carregamento lento. Quando você usa
esse método, o valor exibido pelo logcat é o tempo decorrido entre a
criação do objeto do app e o momento em que reportFullyDrawn()
é chamado.
Veja um exemplo da saída do logcat:
system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
Às vezes, a saída do logcat inclui um tempo total
, conforme discutido em
Tempo para exibição inicial.
Se você descobrir que os tempos de exibição estão mais lentos do que o esperado, tente identificar os gargalos no processo de inicialização.
Identificar gargalos
Uma boa maneira de procurar gargalos é usando o CPU Profiler do Android Studio. Para mais informações, consulte Inspecionar atividades de CPU com o CPU Profiler.
Você também pode saber mais sobre possíveis gargalos usando o rastreamento inline nos
métodos onCreate()
dos seus apps e atividades. Para mais informações sobre o rastreamento inline,
consulte a documentação das funções Trace
e a
visão geral do rastreamento do sistema.
Conhecer problemas comuns
Esta seção discute vários problemas que geralmente afetam o desempenho da inicialização dos apps. Esses problemas referem-se principalmente à inicialização de apps e objetos de atividade, bem como ao carregamento de telas.
Inicialização de apps pesados
O desempenho de inicialização pode ser afetado quando seu código modifica o objeto Application
e executa um trabalho pesado ou lógica complexa ao inicializar esse objeto.
Seu app poderá perder tempo durante a inicialização se as subclasses de Application executarem
inicializações que não precisam ser realizadas. Algumas inicializações podem ser
completamente desnecessárias. Por exemplo, inicializar informações sobre o estado da
atividade principal quando o app foi iniciado em resposta a uma intent.
Com uma intent, o app usa apenas um subconjunto dos dados de estado inicializados
anteriormente.
Outros desafios durante a inicialização do app incluem eventos de coleta de lixo impactantes ou numerosos, ou E/S de disco que aconteçam simultaneamente com a inicialização, bloqueando ainda mais o processo de inicialização. A coleta de lixo é especialmente uma consideração no tempo de execução do Dalvik. O tempo de execução de ART executa a coleta de lixo simultaneamente, minimizando o impacto dessa operação.
Diagnosticar o problema
Você pode usar o rastreamento de métodos ou in-line para tentar diagnosticar o problema.
Rastreamento de métodos
A execução do CPU Profiler revela que o método
callApplicationOnCreate()
finalmente chama seu método
com.example.customApplication.onCreate
. Se a ferramenta mostrar que esses
métodos estão demorando muito para terminar a execução, você precisará explorar mais
para ver qual trabalho está ocorrendo.
Rastreamento in-line
Use o rastreamento in-line para investigar causas prováveis, incluindo:
- A função
onCreate()
inicial do app. - Quaisquer objetos singleton que seu app inicializa.
- E/S de disco, desserialização ou loop apertado que possa estar ocorrendo durante o gargalo.
Soluções para o problema
Se o problema está nas inicializações desnecessárias ou na E/S de disco, a solução é a inicialização lenta. Em outras palavras, só é necessário inicializar objetos que sejam imediatamente necessários. Em vez de criar objetos estáticos globais, mude para um padrão Singleton, em que o app inicializa objetos apenas na primeira vez que eles são necessários.
Além disso, você pode usar um framework de injeção de dependências como Hilt, que cria objetos e dependências quando injetados pela primeira vez.
Se o app usa provedores de conteúdo para inicializar componentes de apps na inicialização, considere usar a biblioteca App Startup.
Inicialização de atividades pesadas
A criação de atividades geralmente envolve muito trabalho com sobrecarga. Muitas vezes, há oportunidades de otimizar esse trabalho para melhorar o desempenho. Tais problemas comuns incluem:
- Inflar layouts grandes ou complexos.
- Bloquear desenho de tela em disco ou E/S de rede.
- Carregar e decodificar bitmaps.
- Fazer varredura de
objetos
VectorDrawable
. - Inicializar outros subsistemas da atividade.
Diagnosticar o problema
Nesse caso também, o rastreamento de métodos e in-line podem ser úteis.
Rastreamento de métodos
Ao usar o CPU Profiler, preste atenção aos construtores de subclasse
Application
e
aos métodos com.example.customApplication.onCreate()
.
Se a ferramenta mostrar que esses métodos estão demorando muito para terminar a execução, você precisará explorar mais para ver qual trabalho está ocorrendo.
Rastreamento in-line
Use o rastreamento in-line para investigar causas prováveis, incluindo:
- A função
onCreate()
inicial do seu app. - Qualquer objeto singleton global inicializado.
- E/S de disco, desserialização ou loop apertado que possa estar ocorrendo durante o gargalo.
Soluções para o problema
Há muitos gargalos em potencial, mas dois problemas e soluções comuns são os seguintes:
- Quanto maior for sua hierarquia de visualizações, mais tempo o app levará para inflá-la.
Você pode executar duas etapas para solucionar esse problema:
- Nivelar sua hierarquia de visualizações, reduzindo layouts redundantes ou aninhados.
- Não inflar partes da IU que não precisam estar visíveis durante a
inicialização. Em vez disso, use um objeto
ViewStub
como um marcador para sub-hierarquias que o app pode inflar em um momento mais apropriado.
- Colocar toda a inicialização de recursos na linha de execução principal também
pode deixar a inicialização lenta. Você pode solucionar esse problema da seguinte maneira:
- Mova toda a inicialização de recursos para outra linha de execução, para que o app possa inicializá-los lentamente.
- Permita que o app carregue e mostre as visualizações e só depois atualize as propriedades visuais que dependem de bitmaps e outros recursos.
Telas de apresentação personalizadas
Talvez você veja um tempo extra durante a inicialização se tiver usado um dos seguintes métodos para implementar uma tela de apresentação personalizada no Android 11 (API de nível 30) ou versões anteriores:
- O atributo de tema
windowDisablePreview
para desativar a tela em branco inicial desenhada pelo sistema durante a inicialização - Uma atividade dedicada
A partir do Android 12, é necessário migrar para a API
SplashScreen
.
Essa API possibilita um tempo de inicialização mais rápido e também
um ajuste na tela de apresentação das seguintes maneiras:
- Defina um tema para mudar a aparência da tela de apresentação
- Controle por quanto tempo a tela de apresentação é exibida
- Determine de quanto tempo a mais a animação da tela de apresentação precisa e processe a animação para dispensar a tela de apresentação
Além disso, a biblioteca de compatibilidade faz o backport da API SplashScreen para ativar a compatibilidade com versões anteriores e criar uma aparência consistente para exibição da tela de apresentação em todas as versões do Android.
Para mais detalhes, consulte o guia Migrar a implementação de tela de apresentação.